{"action":"created","comment":{"url":"https://api.github.com/repos/apache/flink/pulls/comments/31063043","id":31063043,"diff_hunk":"@@ -20,7 +21,329 @@ specific language governing permissions and limitations\n under the License.\n -->\n \n+The Flink community highly appreciates all sorts of contributions to FlinkML.\n+FlinkML offers people interested in machine learning to work on a highly active open source project which makes scalable ML reality.\n+The following document describes how to contribute to FlinkML.\n+\n * This will be replaced by the TOC\n {:toc}\n \n-Coming soon. In the meantime, check our list of [open issues on JIRA](https://issues.apache.org/jira/browse/FLINK-1748?jql=component%20%3D%20%22Machine%20Learning%20Library%22%20AND%20project%20%3D%20FLINK%20AND%20resolution%20%3D%20Unresolved%20ORDER%20BY%20priority%20DESC)\n+## Getting Started\n+\n+In order to get started first read Flink's [contribution guide](http://flink.apache.org/how-to-contribute.html).\n+Everything from this guide also applies to FlinkML.\n+\n+## Pick a Topic\n+\n+If you are looking for some new ideas, then you should check out the list of [unresolved issues on JIRA](https://issues.apache.org/jira/issues/?jql=component%20%3D%20%22Machine%20Learning%20Library%22%20AND%20project%20%3D%20FLINK%20AND%20resolution%20%3D%20Unresolved%20ORDER%20BY%20priority%20DESC).\n+Once you decide to contribute to one of these issues, you should take ownership of it and track your progress with this issue.\n+That way, the other contributors know the state of the different issues and redundant work is avoided.\n+\n+If you already know what you want to contribute to FlinkML all the better.\n+It is still advisable to create a JIRA issue for your idea to tell the Flink community what you want to do, though.\n+\n+## Testing\n+\n+New contributions should come with tests to verify the correct behavior of the algorithm.\n+The tests help to maintain the algorithm's correctness throughout code changes, e.g. refactorings.\n+\n+We distinguish between unit tests, which are executed during maven's test phase, and integration tests, which are executed during maven's verify phase.\n+Maven automatically makes this distinction by using the following naming rules:\n+All test cases whose class name ends with a suffix fulfilling the regular expression `(IT|Integration)(Test|Suite|Case)`, are considered integration tests.\n+The rest are considered unit tests and should only test behavior which is local to the component under test.\n+\n+An integration test is a test which requires the full Flink system to be started.\n+In order to do that properly, all integration test cases have to mix in the trait `FlinkTestBase`.\n+This trait will set the right `ExecutionEnvironment` so that the test will be executed on a special `FlinkMiniCluster` designated for testing purposes.\n+Thus, an integration test could look the following:\n+\n+{% highlight scala %}\n+class ExampleITSuite extends FlatSpec with FlinkTestBase {\n+  behavior of \"An example algorithm\"\n+  \n+  it should \"do something\" in {\n+    ...\n+  }\n+}\n+{% endhighlight %}\n+\n+The test style does not have to be `FlatSpec` but can be any other scalatest `Suite` subclass. \n+\n+## Documentation\n+\n+When contributing new algorithms, it is required to add code comments describing the functioning of the algorithm and its parameters with which the user can control its behavior.\n+Additionally, we would like to encourage contributors to add this information to the online documentation.\n+The online documentation for FlinkML's components can be found in the directory `docs/libs/ml`.\n+\n+Every new algorithm is described by a single markdown file.\n+This file should contain at least the following points:\n+\n+1. What does the algorithm do\n+2. How does the algorithm work (or reference to description) \n+3. Parameter description with default values\n+4. Code snippet showing how the algorithm is used\n+\n+In order to use latex syntax in the markdown file, you have to include `mathjax: include` in the YAML front matter.\n+ \n+{% highlight java %}\n+---\n+mathjax: include\n+title: Example title\n+---\n+{% endhighlight %}\n+\n+In order to use displayed mathematics, you have to put your latex code in `$$ ... $$`.\n+For in-line mathematics, use `$ ... $`.\n+Additionally some predefined latex commands are included into the scope of your markdown file.\n+See `docs/_include/latex_commands.html` for the complete list of predefined latex commands.\n+\n+## Contributing\n+\n+Once you have implemented the algorithm with adequate test coverage and added documentation, you are ready to open a pull request.\n+Details of how to open a pull request can be found [here](http://flink.apache.org/how-to-contribute.html#contributing-code--documentation). \n+\n+## How to Implement a Pipeline Operator\n+\n+FlinkML follows the principle to make machine learning as easy and accessible as possible.\n+Therefore, it supports a flexible pipelining mechanism which allows users to quickly define their analysis pipelines consisting of a multitude of different components.\n+A pipeline operator is either a `Transformer` or a `Predictor`.\n+A `Transformer` can be fitted to training data and transforms data from one format into another format.\n+A scaler which changes the mean and variance of its input data according to the mean and variance of some training data is an example for a `Transformer`.\n+In contrast, a `Predictor` encapsulates a data model and the corresponding logic to train it.\n+Once a `Predictor` has trained the model, it can be used to make new predictions.\n+A support vector machine which is first trained to obtain the support vectors and then used to classify data points is an example for a `Predictor`.\n+A general description of FlinkML's pipelining can be found [here]({{site.baseurl}}/libs/ml/pipelines.html).\n+In order to support the pipelining, algorithms have to adhere to a certain design pattern, which we will describe next.\n+\n+Let's assume that we want to implement a pipeline operator which changes the mean of your data.\n+At first, we have to reflect which type of pipeline operator it is.\n+Since centering data is a common preprocessing step in any analysis pipeline, we will implement it as a `Transformer`.\n+Therefore, we first create a `MeanTransformer` class which inherits from `Transformer`\n+\n+{% highlight scala %}\n+class MeanTransformer extends Transformer[Centering] {}\n+{% endhighlight %}\n+\n+Since we want to be able to configure the mean of the resulting data, we have to add a configuration parameter.\n+\n+{% highlight scala %}\n+class MeanTransformer extends Transformer[Centering] {\n+  def setMean(mean: Double): Mean = {\n+    parameters.add(MeanTransformer.Mean, mu)\n+  }\n+}\n+\n+object MeanTransformer {\n+  case object Mean extends Parameter[Double] {\n+    override val defaultValue: Option[Double] = Some(0.0)\n+  }\n+  \n+  def apply(): MeanTransformer = new MeanTransformer\n+}\n+{% endhighlight %}\n+\n+Parameters are defined in the companion object of the transformer class and extend the `Parameter` class.\n+The default value will be used if no other value has been set by the user of this component.\n+If no default value has been specified, meaning that `defaultValue = None`, then the algorithm has to handle this situation accordingly.\n+\n+We can now instantiate a `MeanTransformer` object and set the mean value of the transformed data.\n+But we still have to implement how the transformation works.\n+The workflow can be separated into two phases.\n+Within the first phase, the transformer learns the mean of the given training data.\n+This knowledge can then be used in the second phase to transform the provided data with respect to the configured resulting mean value.\n+\n+The learning of the mean can be implemented within the `fit` operation of a `Transformer`.\n+Within the `fit` operation, a pipeline component is trained with respect to the given training data.\n+The algorithm is, however, **not** implemented by overriding the `fit` method but by providing an implementation of a corresponding `FitOperation` for the correct type.\n+Taking a look at the definition of the `fit` method in `Estimator`, which is the parent class of `Transformer`, reveals what why this is the case.\n+\n+{% highlight scala %}\n+trait Estimator[Self] extends WithParameters with Serializable {\n+  that: Self =>\n+\n+  def fit[Training](\n+      training: DataSet[Training],\n+      fitParameters: ParameterMap = ParameterMap.Empty)\n+      (implicit fitOperation: FitOperation[Self, Training]): Unit = {\n+    FlinkMLTools.registerFlinkMLTypes(training.getExecutionEnvironment)\n+    fitOperation.fit(this, fitParameters, training)\n+  }\n+}\n+{% endhighlight %}\n+\n+We see that the `fit` method is called with an input data set of type `Training`, an optional parameter list and in the second parameter list with an implicit parameter of type `FitOperation`.\n+Within the body of the function, first some machine learning types are registered and then the `fit` method of the `FitOperation` parameter is called.\n+The instance gives itself, the parameter map and the training data set as a parameters to the method.\n+Thus, all the program logic takes place within the `FitOperation`.\n+\n+The `FitOperation` has two type parameters.\n+The first defines the pipeline operator type for which this `FitOperation` shall work and the second type parameter defines the type of the data set elements.\n+If we first wanted to implement the `MeanTransformer` to work on `DenseVector`, we would, thus, have to provide an implementation for `FitOperation[MeanTransformer, DenseVector]`.\n+ \n+{% highlight scala %}\n+val denseVectorMeanFitOperation = new FitOperation[MeanTransformer, DenseVector] {\n+  override def fit(instance: MeanTransformer, fitParameters: ParameterMap, input: DataSet[DenseVector]) : Unit = {\n+    import org.apache.flink.ml.math.Breeze._\n+    val meanTrainingData: DataSet[DenseVector] = input\n+      .map{ x => (x.asBreeze, 1) }\n+      .reduce{\n+        (left, right) => \n+          (left._1 + right._1, left._2 + right._2) \n+      }\n+      .map{ p => (p._1/p._2).fromBreeze }\n+  }\n+}\n+{% endhighlight %}\n+\n+A `FitOperation[T, I]` has a `fit` method which is called with an instance of type `T`, a parameter map and an input `DataSet[I]`.\n+In our case `T=MeanTransformer` and `I=DenseVector`.\n+The parameter map is necessary if our fit step depends on some parameter values which were not given directly at creation time of the `Transformer`.\n+The `FitOperation` of the `MeanTransformer` sums the `DenseVector` instances of the given input data set up and divides the result by the total number of vectors.\n+That way, we obtain a `DataSet[DenseVector]` with a single element which is the mean value.\n+\n+But if we look closely at the implementation, we see that the result of the mean computation is never stored anywhere.\n+If we want to use this knowledge in a later step to adjust the mean of some other input, we have to keep it around.\n+And here is where the parameter of type `MeanTransformer` which is given to the `fit` method comes into play.\n+We can use this instance to store state, which is used by a subsequent `transform` operation which works on the same object.\n+But first we have to extend `MeanTransformer` by a member field and then adjust the `FitOperation` implementation.\n+\n+{% highlight scala %}\n+class MeanTransformer extends Transformer[Centering] {\n+  var meanOption: Option[DataSet[DenseVector]] = None\n+\n+  def setMean(mean: Double): Mean = {\n+    parameters.add(MeanTransformer.Mean, mu)\n+  }\n+}\n+\n+val denseVectorMeanFitOperation = new FitOperation[MeanTransformer, DenseVector] {\n+  override def fit(instance: MeanTransformer, fitParameters: ParameterMap, input: DataSet[DenseVector]) : Unit = {\n+    import org.apache.flink.ml.math.Breeze._\n+    \n+    instance.meanOption = Some(input\n+      .map{ x => (x.asBreeze, 1) }\n+      .reduce{\n+        (left, right) => \n+          (left._1 + right._1, left._2 + right._2) \n+      }\n+      .map{ p => (p._1/p._2).fromBreeze })\n+  }\n+}\n+{% endhighlight %}\n+\n+If we look at the `transform` method in `Transformer`, we will see that we also need an implementation of `TransformOperation`.\n+A possible mean transforming implementation could look the following.","path":"docs/libs/ml/contribution_guide.md","position":224,"original_position":224,"commit_id":"a3c912e5cf7b310871a78f72fce3136bf63c85dd","original_commit_id":"a3c912e5cf7b310871a78f72fce3136bf63c85dd","user":{"login":"tillrohrmann","id":5756858,"avatar_url":"https://avatars.githubusercontent.com/u/5756858?v=3","gravatar_id":"","url":"https://api.github.com/users/tillrohrmann","html_url":"https://github.com/tillrohrmann","followers_url":"https://api.github.com/users/tillrohrmann/followers","following_url":"https://api.github.com/users/tillrohrmann/following{/other_user}","gists_url":"https://api.github.com/users/tillrohrmann/gists{/gist_id}","starred_url":"https://api.github.com/users/tillrohrmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tillrohrmann/subscriptions","organizations_url":"https://api.github.com/users/tillrohrmann/orgs","repos_url":"https://api.github.com/users/tillrohrmann/repos","events_url":"https://api.github.com/users/tillrohrmann/events{/privacy}","received_events_url":"https://api.github.com/users/tillrohrmann/received_events","type":"User","site_admin":false},"body":":+1:","created_at":"2015-05-26T18:18:16Z","updated_at":"2015-05-26T18:18:16Z","html_url":"https://github.com/apache/flink/pull/727#discussion_r31063043","pull_request_url":"https://api.github.com/repos/apache/flink/pulls/727","_links":{"self":{"href":"https://api.github.com/repos/apache/flink/pulls/comments/31063043"},"html":{"href":"https://github.com/apache/flink/pull/727#discussion_r31063043"},"pull_request":{"href":"https://api.github.com/repos/apache/flink/pulls/727"}}},"pull_request":{"url":"https://api.github.com/repos/apache/flink/pulls/727","id":36222244,"html_url":"https://github.com/apache/flink/pull/727","diff_url":"https://github.com/apache/flink/pull/727.diff","patch_url":"https://github.com/apache/flink/pull/727.patch","issue_url":"https://api.github.com/repos/apache/flink/issues/727","number":727,"state":"open","locked":false,"title":"[FLINK-2073] [ml] [docs] Adds contribution guide","user":{"login":"tillrohrmann","id":5756858,"avatar_url":"https://avatars.githubusercontent.com/u/5756858?v=3","gravatar_id":"","url":"https://api.github.com/users/tillrohrmann","html_url":"https://github.com/tillrohrmann","followers_url":"https://api.github.com/users/tillrohrmann/followers","following_url":"https://api.github.com/users/tillrohrmann/following{/other_user}","gists_url":"https://api.github.com/users/tillrohrmann/gists{/gist_id}","starred_url":"https://api.github.com/users/tillrohrmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tillrohrmann/subscriptions","organizations_url":"https://api.github.com/users/tillrohrmann/orgs","repos_url":"https://api.github.com/users/tillrohrmann/repos","events_url":"https://api.github.com/users/tillrohrmann/events{/privacy}","received_events_url":"https://api.github.com/users/tillrohrmann/received_events","type":"User","site_admin":false},"body":"Adds contribution guide and implementation tutorial for new pipeline operators.","created_at":"2015-05-26T16:46:30Z","updated_at":"2015-05-26T18:18:16Z","closed_at":null,"merged_at":null,"merge_commit_sha":"caa230ca38b13f71c27d6bb4bf5cfc5aa2f73c69","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/flink/pulls/727/commits","review_comments_url":"https://api.github.com/repos/apache/flink/pulls/727/comments","review_comment_url":"https://api.github.com/repos/apache/flink/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/flink/issues/727/comments","statuses_url":"https://api.github.com/repos/apache/flink/statuses/a3c912e5cf7b310871a78f72fce3136bf63c85dd","head":{"label":"tillrohrmann:mlContributionGuide","ref":"mlContributionGuide","sha":"a3c912e5cf7b310871a78f72fce3136bf63c85dd","user":{"login":"tillrohrmann","id":5756858,"avatar_url":"https://avatars.githubusercontent.com/u/5756858?v=3","gravatar_id":"","url":"https://api.github.com/users/tillrohrmann","html_url":"https://github.com/tillrohrmann","followers_url":"https://api.github.com/users/tillrohrmann/followers","following_url":"https://api.github.com/users/tillrohrmann/following{/other_user}","gists_url":"https://api.github.com/users/tillrohrmann/gists{/gist_id}","starred_url":"https://api.github.com/users/tillrohrmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tillrohrmann/subscriptions","organizations_url":"https://api.github.com/users/tillrohrmann/orgs","repos_url":"https://api.github.com/users/tillrohrmann/repos","events_url":"https://api.github.com/users/tillrohrmann/events{/privacy}","received_events_url":"https://api.github.com/users/tillrohrmann/received_events","type":"User","site_admin":false},"repo":{"id":20681108,"name":"flink","full_name":"tillrohrmann/flink","owner":{"login":"tillrohrmann","id":5756858,"avatar_url":"https://avatars.githubusercontent.com/u/5756858?v=3","gravatar_id":"","url":"https://api.github.com/users/tillrohrmann","html_url":"https://github.com/tillrohrmann","followers_url":"https://api.github.com/users/tillrohrmann/followers","following_url":"https://api.github.com/users/tillrohrmann/following{/other_user}","gists_url":"https://api.github.com/users/tillrohrmann/gists{/gist_id}","starred_url":"https://api.github.com/users/tillrohrmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tillrohrmann/subscriptions","organizations_url":"https://api.github.com/users/tillrohrmann/orgs","repos_url":"https://api.github.com/users/tillrohrmann/repos","events_url":"https://api.github.com/users/tillrohrmann/events{/privacy}","received_events_url":"https://api.github.com/users/tillrohrmann/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tillrohrmann/flink","description":"Mirror of Apache Flink","fork":true,"url":"https://api.github.com/repos/tillrohrmann/flink","forks_url":"https://api.github.com/repos/tillrohrmann/flink/forks","keys_url":"https://api.github.com/repos/tillrohrmann/flink/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tillrohrmann/flink/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tillrohrmann/flink/teams","hooks_url":"https://api.github.com/repos/tillrohrmann/flink/hooks","issue_events_url":"https://api.github.com/repos/tillrohrmann/flink/issues/events{/number}","events_url":"https://api.github.com/repos/tillrohrmann/flink/events","assignees_url":"https://api.github.com/repos/tillrohrmann/flink/assignees{/user}","branches_url":"https://api.github.com/repos/tillrohrmann/flink/branches{/branch}","tags_url":"https://api.github.com/repos/tillrohrmann/flink/tags","blobs_url":"https://api.github.com/repos/tillrohrmann/flink/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tillrohrmann/flink/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tillrohrmann/flink/git/refs{/sha}","trees_url":"https://api.github.com/repos/tillrohrmann/flink/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tillrohrmann/flink/statuses/{sha}","languages_url":"https://api.github.com/repos/tillrohrmann/flink/languages","stargazers_url":"https://api.github.com/repos/tillrohrmann/flink/stargazers","contributors_url":"https://api.github.com/repos/tillrohrmann/flink/contributors","subscribers_url":"https://api.github.com/repos/tillrohrmann/flink/subscribers","subscription_url":"https://api.github.com/repos/tillrohrmann/flink/subscription","commits_url":"https://api.github.com/repos/tillrohrmann/flink/commits{/sha}","git_commits_url":"https://api.github.com/repos/tillrohrmann/flink/git/commits{/sha}","comments_url":"https://api.github.com/repos/tillrohrmann/flink/comments{/number}","issue_comment_url":"https://api.github.com/repos/tillrohrmann/flink/issues/comments{/number}","contents_url":"https://api.github.com/repos/tillrohrmann/flink/contents/{+path}","compare_url":"https://api.github.com/repos/tillrohrmann/flink/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tillrohrmann/flink/merges","archive_url":"https://api.github.com/repos/tillrohrmann/flink/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tillrohrmann/flink/downloads","issues_url":"https://api.github.com/repos/tillrohrmann/flink/issues{/number}","pulls_url":"https://api.github.com/repos/tillrohrmann/flink/pulls{/number}","milestones_url":"https://api.github.com/repos/tillrohrmann/flink/milestones{/number}","notifications_url":"https://api.github.com/repos/tillrohrmann/flink/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tillrohrmann/flink/labels{/name}","releases_url":"https://api.github.com/repos/tillrohrmann/flink/releases{/id}","created_at":"2014-06-10T10:19:35Z","updated_at":"2015-04-21T08:56:37Z","pushed_at":"2015-05-26T16:45:48Z","git_url":"git://github.com/tillrohrmann/flink.git","ssh_url":"git@github.com:tillrohrmann/flink.git","clone_url":"https://github.com/tillrohrmann/flink.git","svn_url":"https://github.com/tillrohrmann/flink","homepage":null,"size":51213,"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":"apache:master","ref":"master","sha":"7d6df2e60723ae3c751b8e74f26ceae0512f4a21","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":20587599,"name":"flink","full_name":"apache/flink","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/flink","description":"Mirror of Apache Flink","fork":false,"url":"https://api.github.com/repos/apache/flink","forks_url":"https://api.github.com/repos/apache/flink/forks","keys_url":"https://api.github.com/repos/apache/flink/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/flink/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/flink/teams","hooks_url":"https://api.github.com/repos/apache/flink/hooks","issue_events_url":"https://api.github.com/repos/apache/flink/issues/events{/number}","events_url":"https://api.github.com/repos/apache/flink/events","assignees_url":"https://api.github.com/repos/apache/flink/assignees{/user}","branches_url":"https://api.github.com/repos/apache/flink/branches{/branch}","tags_url":"https://api.github.com/repos/apache/flink/tags","blobs_url":"https://api.github.com/repos/apache/flink/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/flink/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/flink/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/flink/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/flink/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/flink/languages","stargazers_url":"https://api.github.com/repos/apache/flink/stargazers","contributors_url":"https://api.github.com/repos/apache/flink/contributors","subscribers_url":"https://api.github.com/repos/apache/flink/subscribers","subscription_url":"https://api.github.com/repos/apache/flink/subscription","commits_url":"https://api.github.com/repos/apache/flink/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/flink/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/flink/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/flink/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/flink/contents/{+path}","compare_url":"https://api.github.com/repos/apache/flink/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/flink/merges","archive_url":"https://api.github.com/repos/apache/flink/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/flink/downloads","issues_url":"https://api.github.com/repos/apache/flink/issues{/number}","pulls_url":"https://api.github.com/repos/apache/flink/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/flink/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/flink/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/flink/labels{/name}","releases_url":"https://api.github.com/repos/apache/flink/releases{/id}","created_at":"2014-06-07T07:00:10Z","updated_at":"2015-05-26T11:16:36Z","pushed_at":"2015-05-26T18:05:59Z","git_url":"git://github.com/apache/flink.git","ssh_url":"git@github.com:apache/flink.git","clone_url":"https://github.com/apache/flink.git","svn_url":"https://github.com/apache/flink","homepage":null,"size":3305734,"stargazers_count":423,"watchers_count":423,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":265,"mirror_url":"git://git.apache.org/incubator-flink.git","open_issues_count":50,"forks":265,"open_issues":50,"watchers":423,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/flink/pulls/727"},"html":{"href":"https://github.com/apache/flink/pull/727"},"issue":{"href":"https://api.github.com/repos/apache/flink/issues/727"},"comments":{"href":"https://api.github.com/repos/apache/flink/issues/727/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/flink/pulls/727/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/flink/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/flink/pulls/727/commits"},"statuses":{"href":"https://api.github.com/repos/apache/flink/statuses/a3c912e5cf7b310871a78f72fce3136bf63c85dd"}}}}