{"action":"created","comment":{"url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/comments/43589764","id":43589764,"diff_hunk":"@@ -0,0 +1,315 @@\n+/*\n+ * Copyright © 2015 Cask Data, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n+ * use this file except in compliance with the License. You may obtain a copy of\n+ * 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, WITHOUT\n+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n+ * License for the specific language governing permissions and limitations under\n+ * the License.\n+ */\n+\n+package co.cask.hydrator.plugin;\n+\n+import co.cask.cdap.api.annotation.Description;\n+import co.cask.cdap.api.annotation.Name;\n+import co.cask.cdap.api.annotation.Plugin;\n+import co.cask.cdap.api.common.Bytes;\n+import co.cask.cdap.api.data.format.StructuredRecord;\n+import co.cask.cdap.api.data.schema.Schema;\n+import co.cask.cdap.api.data.schema.Schema.Field;\n+import co.cask.cdap.api.plugin.PluginConfig;\n+import co.cask.cdap.etl.api.Emitter;\n+import co.cask.cdap.etl.api.PipelineConfigurer;\n+import co.cask.cdap.etl.api.Transform;\n+import co.cask.cdap.etl.api.TransformContext;\n+import com.google.common.collect.Maps;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+import org.xerial.snappy.Snappy;\n+\n+import java.io.ByteArrayInputStream;\n+import java.io.ByteArrayOutputStream;\n+import java.io.IOException;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.zip.GZIPInputStream;\n+import java.util.zip.ZipEntry;\n+import java.util.zip.ZipInputStream;\n+\n+/**\n+ * Decompreses the configured fields using the algorithms specified.\n+ */\n+@Plugin(type = \"transform\")\n+@Name(\"Decompressor\")\n+@Description(\"Decompresses configured fields using the algorithms specified.\")\n+public final class Decompressor extends Transform<StructuredRecord, StructuredRecord> {\n+  private static final Logger LOG = LoggerFactory.getLogger(Decompressor.class);\n+  private final Config config;\n+\n+  // Output Schema associated with transform output.\n+  private Schema outSchema;\n+\n+  // Output Field name to type map\n+  private Map<String, Schema.Type> outSchemaMap = Maps.newHashMap();\n+\n+  // Map of field to decompressor type.\n+  private final Map<String, DecompressorType> deCompMap = Maps.newTreeMap();\n+\n+  // This is used only for tests, otherwise this is being injected by the ingestion framework.\n+  public Decompressor(Config config) {\n+    this.config = config;\n+  }\n+\n+  private void parseConfiguration(String config) throws IllegalArgumentException {\n+    String[] mappings = config.split(\",\");\n+    for (String mapping : mappings) {\n+      String[] params = mapping.split(\":\");\n+\n+      // If format is not right, then we throw an exception.\n+      if (params.length < 2) {\n+        throw new IllegalArgumentException(\"Configuration \" + mapping + \" is in-correctly formed. \" +\n+                                             \"Format should be <fieldname>:<decompressor-type>\");\n+      }\n+\n+      String field = params[0];\n+      String type = params[1].toUpperCase();\n+      DecompressorType cType = DecompressorType.NONE;\n+\n+      switch(type) {\n+        case \"SNAPPY\":\n+          cType = DecompressorType.SNAPPY;\n+          break;\n+\n+        case \"GZIP\":\n+          cType = DecompressorType.GZIP;\n+          break;\n+\n+        case \"ZIP\":\n+          cType = DecompressorType.ZIP;\n+          break;\n+\n+        case \"NONE\":\n+          cType = DecompressorType.NONE;\n+          break;\n+\n+        default:\n+          throw new IllegalArgumentException(\"Unknown decompressor type \" + type + \" found in mapping \" + mapping);\n+      }\n+      if (deCompMap.containsKey(field)) {\n+        throw new IllegalArgumentException(\"Field \" + field + \" already has decompressor set. Check the mapping.\");\n+      } else {\n+        deCompMap.put(field, cType);\n+      }\n+    }\n+  }\n+\n+  @Override\n+  public void configurePipeline(PipelineConfigurer pipelineConfigurer) throws IllegalArgumentException {\n+    super.configurePipeline(pipelineConfigurer);\n+    parseConfiguration(config.decompressor);\n+    \n+    // Check if schema specified is a valid schema or no.\n+    try {\n+      Schema outputSchema = Schema.parseJson(config.schema);\n+      List<Field> outFields = outputSchema.getFields();\n+      for (Field field : outFields) {\n+        outSchemaMap.put(field.getName(), field.getSchema().getType());\n+      }\n+    } catch (IOException e) {\n+      throw new IllegalArgumentException(\"Format of schema specified is invalid. Please check the format.\");\n+    }\n+    \n+    for (Map.Entry<String, DecompressorType> entry : deCompMap.entrySet()) {\n+      if (!outSchemaMap.containsKey(entry.getKey())) {\n+        throw new IllegalArgumentException(\"Field '\" + entry.getKey() + \"' specified to be decompresed is not \" +\n+                                             \"present in the output schema. Please add field '\" + entry.getKey() + \"'\" +\n+                                             \"to output schema or remove it from decompress\");\n+      }\n+      if (outSchemaMap.get(entry.getKey()) != Schema.Type.BYTES && \n+        outSchemaMap.get(entry.getKey()) != Schema.Type.STRING) {\n+        throw new IllegalArgumentException(\"Field '\" + entry.getKey() + \"' should be of type BYTES or STRING in \" +\n+                                             \"output schema.\");\n+      }\n+    }\n+  }\n+  \n+  @Override\n+  public void initialize(TransformContext context) throws Exception {\n+    super.initialize(context);\n+    parseConfiguration(config.decompressor);\n+    try {\n+      outSchema = Schema.parseJson(config.schema);\n+      List<Field> outFields = outSchema.getFields();\n+      for (Field field : outFields) {\n+        outSchemaMap.put(field.getName(), field.getSchema().getType());\n+      }\n+    } catch (IOException e) {\n+      throw new IllegalArgumentException(\"Format of schema specified is invalid. Please check the format.\");\n+    }\n+  }\n+\n+  @Override\n+  public void transform(StructuredRecord in, Emitter<StructuredRecord> emitter) throws Exception {\n+    StructuredRecord.Builder builder = StructuredRecord.builder(outSchema);\n+\n+    Schema inSchema = in.getSchema();\n+    List<Field> inFields = inSchema.getFields();\n+\n+    // Iterate through input fields. Check if field name is present\n+    // in the fields that need to be decompressed, if it's not then write\n+    // to output as it is.\n+    for (Field field : inFields) {\n+      String name = field.getName();\n+\n+      // Check if output schema also have the same field name. If it's not\n+      // then continue.\n+      if (!outSchemaMap.containsKey(name)) {\n+        continue;\n+      }\n+\n+      Schema.Type outFieldType = outSchemaMap. get(name);\n+\n+      // Check if the input field name is configured to be encoded. If the field is not\n+      // present or is defined as none, then pass through the field as is.\n+      if (!deCompMap.containsKey(name) || deCompMap.get(name) == DecompressorType.NONE) {\n+        builder.set(name, in.get(name));\n+      } else {\n+        // Now, the input field should be of type byte[]\n+        byte[] obj = new byte[0];\n+        if (field.getSchema().getType() == Schema.Type.BYTES){\n+          obj = in.get(name);\n+        } else {\n+          LOG.error(\"Input field '\" + name + \"' should be of type BYTES to decompress. It's currently of type\" +\n+                      \"'\" + field.getSchema().getType().toString());\n+        }\n+\n+        // Now, based on the encode type configured for the field - encode the byte[] of the\n+        // value.\n+        byte[] outValue = new byte[0];\n+        DecompressorType type = deCompMap.get(name);\n+        if (type == DecompressorType.SNAPPY) {\n+          outValue = Snappy.uncompress(obj);\n+        } else if (type == DecompressorType.ZIP) {\n+          outValue = unzip(obj);\n+        } else if (type == DecompressorType.GZIP) {\n+          outValue = ungzip(obj);\n+        }\n+\n+        // Depending on the output field type, either convert it to\n+        // Bytes or to String.\n+        if (outValue != null) {\n+          if (outFieldType == Schema.Type.BYTES) {\n+            builder.set(name, outValue);\n+          } else if (outFieldType == Schema.Type.STRING) {\n+            builder.set(name, Bytes.toString(outValue));\n+          }\n+        }\n+      }\n+    }\n+    emitter.emit(builder.build());\n+  }\n+\n+  /**\n+   * Decompresses using GZIP Algorithm. \n+   */\n+  private byte[] ungzip(byte[] body) {\n+    ByteArrayInputStream bytein = new ByteArrayInputStream(body);\n+    GZIPInputStream gzin = null;\n+    try {\n+      gzin = new GZIPInputStream(bytein);\n+      ByteArrayOutputStream byteout = new ByteArrayOutputStream();\n+      int res = 0;\n+      byte buf[] = new byte[1024];\n+      while (res >= 0) {\n+        res = gzin.read(buf, 0, buf.length);\n+        if (res > 0) {\n+          byteout.write(buf, 0, res);\n+        }\n+      }\n+      byte uncompressed[] = byteout.toByteArray();\n+      return uncompressed;\n+    } catch (IOException e) {\n+      // Most of operations here are in memory. So, we shouldn't get here. \n+      // Logging here is not an option. \n+      return null;\n+    } \n+  }\n+\n+  /**\n+   * Decompresses using ZIP Algorithm.\n+   */\n+  private byte[] unzip(byte[] body)  {\n+    ByteArrayInputStream bytein = new ByteArrayInputStream(body);","path":"transform-plugins/src/main/java/co/cask/hydrator/plugin/Decompressor.java","position":248,"original_position":248,"commit_id":"897a25135050c635166afceb7abbd72582cd5d8f","original_commit_id":"897a25135050c635166afceb7abbd72582cd5d8f","user":{"login":"bdmogal","id":3895099,"avatar_url":"https://avatars.githubusercontent.com/u/3895099?v=3","gravatar_id":"","url":"https://api.github.com/users/bdmogal","html_url":"https://github.com/bdmogal","followers_url":"https://api.github.com/users/bdmogal/followers","following_url":"https://api.github.com/users/bdmogal/following{/other_user}","gists_url":"https://api.github.com/users/bdmogal/gists{/gist_id}","starred_url":"https://api.github.com/users/bdmogal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bdmogal/subscriptions","organizations_url":"https://api.github.com/users/bdmogal/orgs","repos_url":"https://api.github.com/users/bdmogal/repos","events_url":"https://api.github.com/users/bdmogal/events{/privacy}","received_events_url":"https://api.github.com/users/bdmogal/received_events","type":"User","site_admin":false},"body":"same as above?","created_at":"2015-11-01T23:18:41Z","updated_at":"2015-11-01T23:18:41Z","html_url":"https://github.com/caskdata/hydrator-plugins/pull/48#discussion_r43589764","pull_request_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48","_links":{"self":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/comments/43589764"},"html":{"href":"https://github.com/caskdata/hydrator-plugins/pull/48#discussion_r43589764"},"pull_request":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48"}}},"pull_request":{"url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48","id":49364334,"html_url":"https://github.com/caskdata/hydrator-plugins/pull/48","diff_url":"https://github.com/caskdata/hydrator-plugins/pull/48.diff","patch_url":"https://github.com/caskdata/hydrator-plugins/pull/48.patch","issue_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/48","number":48,"state":"open","locked":false,"title":"Decompressor transform","user":{"login":"nitinmotgi","id":1365919,"avatar_url":"https://avatars.githubusercontent.com/u/1365919?v=3","gravatar_id":"","url":"https://api.github.com/users/nitinmotgi","html_url":"https://github.com/nitinmotgi","followers_url":"https://api.github.com/users/nitinmotgi/followers","following_url":"https://api.github.com/users/nitinmotgi/following{/other_user}","gists_url":"https://api.github.com/users/nitinmotgi/gists{/gist_id}","starred_url":"https://api.github.com/users/nitinmotgi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitinmotgi/subscriptions","organizations_url":"https://api.github.com/users/nitinmotgi/orgs","repos_url":"https://api.github.com/users/nitinmotgi/repos","events_url":"https://api.github.com/users/nitinmotgi/events{/privacy}","received_events_url":"https://api.github.com/users/nitinmotgi/received_events","type":"User","site_admin":false},"body":"Transform that will decompress a field(s).","created_at":"2015-11-01T02:47:54Z","updated_at":"2015-11-01T23:18:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"233de90ccf200cbbbdcb2db6e9843419877c9f5e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48/commits","review_comments_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48/comments","review_comment_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/comments{/number}","comments_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/48/comments","statuses_url":"https://api.github.com/repos/caskdata/hydrator-plugins/statuses/897a25135050c635166afceb7abbd72582cd5d8f","head":{"label":"caskdata:feature/decompressor","ref":"feature/decompressor","sha":"897a25135050c635166afceb7abbd72582cd5d8f","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":39922362,"name":"hydrator-plugins","full_name":"caskdata/hydrator-plugins","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/hydrator-plugins","description":"Cask Hydrator Plugins Repository","fork":false,"url":"https://api.github.com/repos/caskdata/hydrator-plugins","forks_url":"https://api.github.com/repos/caskdata/hydrator-plugins/forks","keys_url":"https://api.github.com/repos/caskdata/hydrator-plugins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/hydrator-plugins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/hydrator-plugins/teams","hooks_url":"https://api.github.com/repos/caskdata/hydrator-plugins/hooks","issue_events_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/hydrator-plugins/events","assignees_url":"https://api.github.com/repos/caskdata/hydrator-plugins/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/hydrator-plugins/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/hydrator-plugins/tags","blobs_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/hydrator-plugins/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/hydrator-plugins/languages","stargazers_url":"https://api.github.com/repos/caskdata/hydrator-plugins/stargazers","contributors_url":"https://api.github.com/repos/caskdata/hydrator-plugins/contributors","subscribers_url":"https://api.github.com/repos/caskdata/hydrator-plugins/subscribers","subscription_url":"https://api.github.com/repos/caskdata/hydrator-plugins/subscription","commits_url":"https://api.github.com/repos/caskdata/hydrator-plugins/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/hydrator-plugins/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/comments{/number}","contents_url":"https://api.github.com/repos/caskdata/hydrator-plugins/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/hydrator-plugins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/hydrator-plugins/merges","archive_url":"https://api.github.com/repos/caskdata/hydrator-plugins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/hydrator-plugins/downloads","issues_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/hydrator-plugins/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/hydrator-plugins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/hydrator-plugins/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/hydrator-plugins/releases{/id}","created_at":"2015-07-30T00:14:48Z","updated_at":"2015-11-01T02:04:39Z","pushed_at":"2015-11-01T21:55:57Z","git_url":"git://github.com/caskdata/hydrator-plugins.git","ssh_url":"git@github.com:caskdata/hydrator-plugins.git","clone_url":"https://github.com/caskdata/hydrator-plugins.git","svn_url":"https://github.com/caskdata/hydrator-plugins","homepage":"http://cdap.io","size":1621,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":5,"forks":1,"open_issues":5,"watchers":1,"default_branch":"develop"}},"base":{"label":"caskdata:develop","ref":"develop","sha":"a5a5e2c8a9054406656bec399650fee378a94823","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":39922362,"name":"hydrator-plugins","full_name":"caskdata/hydrator-plugins","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/hydrator-plugins","description":"Cask Hydrator Plugins Repository","fork":false,"url":"https://api.github.com/repos/caskdata/hydrator-plugins","forks_url":"https://api.github.com/repos/caskdata/hydrator-plugins/forks","keys_url":"https://api.github.com/repos/caskdata/hydrator-plugins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/hydrator-plugins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/hydrator-plugins/teams","hooks_url":"https://api.github.com/repos/caskdata/hydrator-plugins/hooks","issue_events_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/hydrator-plugins/events","assignees_url":"https://api.github.com/repos/caskdata/hydrator-plugins/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/hydrator-plugins/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/hydrator-plugins/tags","blobs_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/hydrator-plugins/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/hydrator-plugins/languages","stargazers_url":"https://api.github.com/repos/caskdata/hydrator-plugins/stargazers","contributors_url":"https://api.github.com/repos/caskdata/hydrator-plugins/contributors","subscribers_url":"https://api.github.com/repos/caskdata/hydrator-plugins/subscribers","subscription_url":"https://api.github.com/repos/caskdata/hydrator-plugins/subscription","commits_url":"https://api.github.com/repos/caskdata/hydrator-plugins/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/hydrator-plugins/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/hydrator-plugins/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/comments{/number}","contents_url":"https://api.github.com/repos/caskdata/hydrator-plugins/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/hydrator-plugins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/hydrator-plugins/merges","archive_url":"https://api.github.com/repos/caskdata/hydrator-plugins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/hydrator-plugins/downloads","issues_url":"https://api.github.com/repos/caskdata/hydrator-plugins/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/hydrator-plugins/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/hydrator-plugins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/hydrator-plugins/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/hydrator-plugins/releases{/id}","created_at":"2015-07-30T00:14:48Z","updated_at":"2015-11-01T02:04:39Z","pushed_at":"2015-11-01T21:55:57Z","git_url":"git://github.com/caskdata/hydrator-plugins.git","ssh_url":"git@github.com:caskdata/hydrator-plugins.git","clone_url":"https://github.com/caskdata/hydrator-plugins.git","svn_url":"https://github.com/caskdata/hydrator-plugins","homepage":"http://cdap.io","size":1621,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":5,"forks":1,"open_issues":5,"watchers":1,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48"},"html":{"href":"https://github.com/caskdata/hydrator-plugins/pull/48"},"issue":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/48"},"comments":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/issues/48/comments"},"review_comments":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48/comments"},"review_comment":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/pulls/48/commits"},"statuses":{"href":"https://api.github.com/repos/caskdata/hydrator-plugins/statuses/897a25135050c635166afceb7abbd72582cd5d8f"}}}}