{"action":"created","comment":{"url":"https://api.github.com/repos/yahoo/squidb/pulls/comments/38989371","id":38989371,"diff_hunk":"@@ -0,0 +1,175 @@\n+/*\n+ * Copyright 2015, Yahoo Inc.\n+ * Copyrights licensed under the Apache 2.0 License.\n+ * See the accompanying LICENSE file for terms.\n+ */\n+package com.yahoo.squidb.processor.plugins;\n+\n+import com.yahoo.aptutils.model.DeclaredTypeName;\n+import com.yahoo.aptutils.utils.AptUtils;\n+import com.yahoo.aptutils.writer.JavaFileWriter;\n+import com.yahoo.squidb.processor.data.ModelSpec;\n+import com.yahoo.squidb.processor.plugins.defaults.properties.generators.PropertyGenerator;\n+\n+import java.io.IOException;\n+import java.util.Set;\n+\n+import javax.lang.model.element.VariableElement;\n+\n+/**\n+ * The Plugin class defines several hooks for plugins to add code to a generated model class. Code generation for a\n+ * model can be broken down into several distinct phases, each of which has one or more corresponding hooks available\n+ * to plugins:\n+ * <ol>\n+ * <li>Declare imports. Plugins can add imports using {@link #addRequiredImports(Set)}</li>\n+ * <li>Begin class declaration. Much of this is fixed, but plugins can add interfaces for the generated class to\n+ * implement using {@link #addInterfacesToImplement(Set)}</li>\n+ * <li>Emitting the table or view schema. This includes property declarations, the Table or View object for the\n+ * model, etc. Plugins can generate code before or after this phase using {@link #beforeEmitSchema(JavaFileWriter)}\n+ * and {@link #afterEmitSchema(JavaFileWriter)}</li>\n+ * <li>Emitting constructors. Plugins can add constructors using {@link #emitConstructors(JavaFileWriter)}. Note\n+ * that several default constructors and a clone() method are emitted by a built-in plugin.</li>\n+ * <li>Emitting methods. Plugins can emit code before methods are declared\n+ * ({@link #beforeEmitMethods(JavaFileWriter)}), emit methods ({@link #emitMethods(JavaFileWriter)}), or emit code\n+ * after methods are emitted ({@link #afterEmitMethods(JavaFileWriter)})</li>\n+ * <li>Emit other helpers. This is the final phase of code generation before the class definition is closed. Plugins\n+ * can generate arbitrary code here using {@link #emitOtherHelpers(JavaFileWriter)}</li>\n+ * </ol>\n+ */\n+public class Plugin {\n+\n+    protected final ModelSpec<?> modelSpec;\n+    protected final AptUtils utils;\n+\n+    /**\n+     * All Plugins are constructed for a particular instance of a {@link ModelSpec}. The plugin should parse the given\n+     * spec to determine what if any code it should run in its overridden methods\n+     *\n+     * @param modelSpec a {@link ModelSpec} representing the spec class\n+     * @param utils annotation processing utilities class\n+     */\n+    public Plugin(ModelSpec<?> modelSpec, AptUtils utils) {\n+        this.modelSpec = modelSpec;\n+        this.utils = utils;\n+    }\n+\n+    /**\n+     * @return true if this plugin may make any changes during code generation for this model spec. The default is true;\n+     * plugins like the default property generator plugins may return false if the model spec is of a different kind\n+     * than the kind they handle. If this method returns false, none of the other methods in this plugin will be called\n+     * during code generation for this model\n+     */\n+    public boolean hasChangesForModelSpec() {\n+        // Subclasses can override if they want to ignore this entire model spec\n+        return true;\n+    }\n+\n+    /**\n+     * @param field a {@link VariableElement} field in a model spec\n+     * @param fieldType the type name of the field\n+     * @return true if the processing of the variable element was claimed by this plugin and should not be processed\n+     * by other plugins\n+     */\n+    public boolean processVariableElement(VariableElement field, DeclaredTypeName fieldType) {\n+        // Stub for subclasses to override\n+        return false;\n+    }\n+\n+    /**\n+     * Called after processing all variable elements in the model spec. Subclasses that want to add additional property\n+     * generators for properties not corresponding to a field in the model spec should override this method and do so\n+     * here by calling {@link ModelSpec#addPropertyGenerator(PropertyGenerator)} or\n+     * {@link ModelSpec#addDeprecatedPropertyGenerator(PropertyGenerator)}\n+     */\n+    public void afterProcessVariableElements() {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Plugin subclasses can override this method to add any imports required by the code they generate to the generated\n+     * model class\n+     *\n+     * @param imports an accumulator set of type names to import\n+     */\n+    public void addRequiredImports(Set<DeclaredTypeName> imports) {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Plugin subclasses can override this method to add any interfaces they want the generated model class to implement\n+     *\n+     * @param interfaces an accumulator set of type names for interfaces to implement\n+     */\n+    public void addInterfacesToImplement(Set<DeclaredTypeName> interfaces) {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called before emitting the table schema (property declarations, the Table/View object, etc.). This is essentially\n+     * the top of the file before anything model-specific exists.\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void beforeEmitSchema(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called after emitting the table schema (property declarations, the Table/View object, etc.)\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void afterEmitSchema(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called to emit constructors for the generated model class. Plugin subclasses can override to add their own\n+     * constructors\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void emitConstructors(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called before emitting methods. Plugin subclasses can generate arbitrary code here. This is called after\n+     * emitting constructors\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void beforeEmitMethods(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called to emit methods. Plugin subclasses can override to add methods to the model definition\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void emitMethods(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called after emitting methods. Plugin subclasses can generate arbitrary code here. This is called after\n+     * emitting methods\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void afterEmitMethods(JavaFileWriter writer) throws IOException {\n+        // Stub for subclasses to override\n+    }\n+\n+    /**\n+     * Called before the generated class definition is finished. Plugin subclasses can override to write any additional\n+     * arbitrary code they want to\n+     *\n+     * @param writer a {@link JavaFileWriter} for writing to\n+     */\n+    public void emitOtherHelpers(JavaFileWriter writer) throws IOException {","path":"squidb-processor/src/com/yahoo/squidb/processor/plugins/Plugin.java","position":171,"original_position":171,"commit_id":"bf85eed1e922a4c9ddc43542ed130b8520966aa7","original_commit_id":"bf85eed1e922a4c9ddc43542ed130b8520966aa7","user":{"login":"jdkoren","id":771156,"avatar_url":"https://avatars.githubusercontent.com/u/771156?v=3","gravatar_id":"","url":"https://api.github.com/users/jdkoren","html_url":"https://github.com/jdkoren","followers_url":"https://api.github.com/users/jdkoren/followers","following_url":"https://api.github.com/users/jdkoren/following{/other_user}","gists_url":"https://api.github.com/users/jdkoren/gists{/gist_id}","starred_url":"https://api.github.com/users/jdkoren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jdkoren/subscriptions","organizations_url":"https://api.github.com/users/jdkoren/orgs","repos_url":"https://api.github.com/users/jdkoren/repos","events_url":"https://api.github.com/users/jdkoren/events{/privacy}","received_events_url":"https://api.github.com/users/jdkoren/received_events","type":"User","site_admin":false},"body":"Maybe rename this? The \"helpers\" part seems strange.","created_at":"2015-09-08T22:43:39Z","updated_at":"2015-09-08T22:43:39Z","html_url":"https://github.com/yahoo/squidb/pull/83#discussion_r38989371","pull_request_url":"https://api.github.com/repos/yahoo/squidb/pulls/83","_links":{"self":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/comments/38989371"},"html":{"href":"https://github.com/yahoo/squidb/pull/83#discussion_r38989371"},"pull_request":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/83"}}},"pull_request":{"url":"https://api.github.com/repos/yahoo/squidb/pulls/83","id":43468593,"html_url":"https://github.com/yahoo/squidb/pull/83","diff_url":"https://github.com/yahoo/squidb/pull/83.diff","patch_url":"https://github.com/yahoo/squidb/pull/83.patch","issue_url":"https://api.github.com/repos/yahoo/squidb/issues/83","number":83,"state":"open","locked":false,"title":"Code generation plugins 2.0","user":{"login":"sbosley","id":622224,"avatar_url":"https://avatars.githubusercontent.com/u/622224?v=3","gravatar_id":"","url":"https://api.github.com/users/sbosley","html_url":"https://github.com/sbosley","followers_url":"https://api.github.com/users/sbosley/followers","following_url":"https://api.github.com/users/sbosley/following{/other_user}","gists_url":"https://api.github.com/users/sbosley/gists{/gist_id}","starred_url":"https://api.github.com/users/sbosley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbosley/subscriptions","organizations_url":"https://api.github.com/users/sbosley/orgs","repos_url":"https://api.github.com/users/sbosley/repos","events_url":"https://api.github.com/users/sbosley/events{/privacy}","received_events_url":"https://api.github.com/users/sbosley/received_events","type":"User","site_admin":false},"body":"Big refactor of how the code generation plugin system works to enable plugins that can do more things. In addition to defining custom handling of fields, plugins can add nearly arbitrary code to model specs using any of the following:\r\n* addInterfacesToImplement\r\n* beforeEmitSchema\r\n* afterEmitSchema\r\n* emitConstructors\r\n* beforeEmitMethods\r\n* emitMethods\r\n* afterEmitMethods\r\n* emitOtherHelpers\r\n\r\nMuch of the core functionality of the code generator (processing the Implements annotation, copying constants from model specs, processing model methods, etc.) has itself been implemented as a collection of default plugins. This also enables part two of this PR: disabling functionality with compile time flags. Users can disable those default plugins with a flag passed to the processor, and can also disable two other things: default content values (if you don't like having defaults in empty model instances) and the convenience getters and setters (if you're concerned about model objects inflating your method count).\r\n\r\nCloses #32 ","created_at":"2015-08-27T00:44:44Z","updated_at":"2015-09-08T22:43:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a87898843a27d5f3d8269c8a7a92df116b5d9192","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/yahoo/squidb/pulls/83/commits","review_comments_url":"https://api.github.com/repos/yahoo/squidb/pulls/83/comments","review_comment_url":"https://api.github.com/repos/yahoo/squidb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/yahoo/squidb/issues/83/comments","statuses_url":"https://api.github.com/repos/yahoo/squidb/statuses/bf85eed1e922a4c9ddc43542ed130b8520966aa7","head":{"label":"sbosley:codegen_plugins","ref":"codegen_plugins","sha":"bf85eed1e922a4c9ddc43542ed130b8520966aa7","user":{"login":"sbosley","id":622224,"avatar_url":"https://avatars.githubusercontent.com/u/622224?v=3","gravatar_id":"","url":"https://api.github.com/users/sbosley","html_url":"https://github.com/sbosley","followers_url":"https://api.github.com/users/sbosley/followers","following_url":"https://api.github.com/users/sbosley/following{/other_user}","gists_url":"https://api.github.com/users/sbosley/gists{/gist_id}","starred_url":"https://api.github.com/users/sbosley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbosley/subscriptions","organizations_url":"https://api.github.com/users/sbosley/orgs","repos_url":"https://api.github.com/users/sbosley/repos","events_url":"https://api.github.com/users/sbosley/events{/privacy}","received_events_url":"https://api.github.com/users/sbosley/received_events","type":"User","site_admin":false},"repo":{"id":34016211,"name":"squidb","full_name":"sbosley/squidb","owner":{"login":"sbosley","id":622224,"avatar_url":"https://avatars.githubusercontent.com/u/622224?v=3","gravatar_id":"","url":"https://api.github.com/users/sbosley","html_url":"https://github.com/sbosley","followers_url":"https://api.github.com/users/sbosley/followers","following_url":"https://api.github.com/users/sbosley/following{/other_user}","gists_url":"https://api.github.com/users/sbosley/gists{/gist_id}","starred_url":"https://api.github.com/users/sbosley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbosley/subscriptions","organizations_url":"https://api.github.com/users/sbosley/orgs","repos_url":"https://api.github.com/users/sbosley/repos","events_url":"https://api.github.com/users/sbosley/events{/privacy}","received_events_url":"https://api.github.com/users/sbosley/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/sbosley/squidb","description":"SquiDB is a SQLite database layer for Android","fork":true,"url":"https://api.github.com/repos/sbosley/squidb","forks_url":"https://api.github.com/repos/sbosley/squidb/forks","keys_url":"https://api.github.com/repos/sbosley/squidb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sbosley/squidb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sbosley/squidb/teams","hooks_url":"https://api.github.com/repos/sbosley/squidb/hooks","issue_events_url":"https://api.github.com/repos/sbosley/squidb/issues/events{/number}","events_url":"https://api.github.com/repos/sbosley/squidb/events","assignees_url":"https://api.github.com/repos/sbosley/squidb/assignees{/user}","branches_url":"https://api.github.com/repos/sbosley/squidb/branches{/branch}","tags_url":"https://api.github.com/repos/sbosley/squidb/tags","blobs_url":"https://api.github.com/repos/sbosley/squidb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sbosley/squidb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sbosley/squidb/git/refs{/sha}","trees_url":"https://api.github.com/repos/sbosley/squidb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sbosley/squidb/statuses/{sha}","languages_url":"https://api.github.com/repos/sbosley/squidb/languages","stargazers_url":"https://api.github.com/repos/sbosley/squidb/stargazers","contributors_url":"https://api.github.com/repos/sbosley/squidb/contributors","subscribers_url":"https://api.github.com/repos/sbosley/squidb/subscribers","subscription_url":"https://api.github.com/repos/sbosley/squidb/subscription","commits_url":"https://api.github.com/repos/sbosley/squidb/commits{/sha}","git_commits_url":"https://api.github.com/repos/sbosley/squidb/git/commits{/sha}","comments_url":"https://api.github.com/repos/sbosley/squidb/comments{/number}","issue_comment_url":"https://api.github.com/repos/sbosley/squidb/issues/comments{/number}","contents_url":"https://api.github.com/repos/sbosley/squidb/contents/{+path}","compare_url":"https://api.github.com/repos/sbosley/squidb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sbosley/squidb/merges","archive_url":"https://api.github.com/repos/sbosley/squidb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sbosley/squidb/downloads","issues_url":"https://api.github.com/repos/sbosley/squidb/issues{/number}","pulls_url":"https://api.github.com/repos/sbosley/squidb/pulls{/number}","milestones_url":"https://api.github.com/repos/sbosley/squidb/milestones{/number}","notifications_url":"https://api.github.com/repos/sbosley/squidb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sbosley/squidb/labels{/name}","releases_url":"https://api.github.com/repos/sbosley/squidb/releases{/id}","created_at":"2015-04-15T20:13:50Z","updated_at":"2015-05-07T22:43:49Z","pushed_at":"2015-08-30T16:12:01Z","git_url":"git://github.com/sbosley/squidb.git","ssh_url":"git@github.com:sbosley/squidb.git","clone_url":"https://github.com/sbosley/squidb.git","svn_url":"https://github.com/sbosley/squidb","homepage":"https://github.com/yahoo/squidb/wiki","size":21044,"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":"yahoo:dev_2.0","ref":"dev_2.0","sha":"e9d5b1cebf1f1196ab79a17218a1db7ec18e046a","user":{"login":"yahoo","id":16574,"avatar_url":"https://avatars.githubusercontent.com/u/16574?v=3","gravatar_id":"","url":"https://api.github.com/users/yahoo","html_url":"https://github.com/yahoo","followers_url":"https://api.github.com/users/yahoo/followers","following_url":"https://api.github.com/users/yahoo/following{/other_user}","gists_url":"https://api.github.com/users/yahoo/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoo/subscriptions","organizations_url":"https://api.github.com/users/yahoo/orgs","repos_url":"https://api.github.com/users/yahoo/repos","events_url":"https://api.github.com/users/yahoo/events{/privacy}","received_events_url":"https://api.github.com/users/yahoo/received_events","type":"Organization","site_admin":false},"repo":{"id":34006895,"name":"squidb","full_name":"yahoo/squidb","owner":{"login":"yahoo","id":16574,"avatar_url":"https://avatars.githubusercontent.com/u/16574?v=3","gravatar_id":"","url":"https://api.github.com/users/yahoo","html_url":"https://github.com/yahoo","followers_url":"https://api.github.com/users/yahoo/followers","following_url":"https://api.github.com/users/yahoo/following{/other_user}","gists_url":"https://api.github.com/users/yahoo/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoo/subscriptions","organizations_url":"https://api.github.com/users/yahoo/orgs","repos_url":"https://api.github.com/users/yahoo/repos","events_url":"https://api.github.com/users/yahoo/events{/privacy}","received_events_url":"https://api.github.com/users/yahoo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/yahoo/squidb","description":"SquiDB is a SQLite database layer for Android","fork":false,"url":"https://api.github.com/repos/yahoo/squidb","forks_url":"https://api.github.com/repos/yahoo/squidb/forks","keys_url":"https://api.github.com/repos/yahoo/squidb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yahoo/squidb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yahoo/squidb/teams","hooks_url":"https://api.github.com/repos/yahoo/squidb/hooks","issue_events_url":"https://api.github.com/repos/yahoo/squidb/issues/events{/number}","events_url":"https://api.github.com/repos/yahoo/squidb/events","assignees_url":"https://api.github.com/repos/yahoo/squidb/assignees{/user}","branches_url":"https://api.github.com/repos/yahoo/squidb/branches{/branch}","tags_url":"https://api.github.com/repos/yahoo/squidb/tags","blobs_url":"https://api.github.com/repos/yahoo/squidb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yahoo/squidb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yahoo/squidb/git/refs{/sha}","trees_url":"https://api.github.com/repos/yahoo/squidb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yahoo/squidb/statuses/{sha}","languages_url":"https://api.github.com/repos/yahoo/squidb/languages","stargazers_url":"https://api.github.com/repos/yahoo/squidb/stargazers","contributors_url":"https://api.github.com/repos/yahoo/squidb/contributors","subscribers_url":"https://api.github.com/repos/yahoo/squidb/subscribers","subscription_url":"https://api.github.com/repos/yahoo/squidb/subscription","commits_url":"https://api.github.com/repos/yahoo/squidb/commits{/sha}","git_commits_url":"https://api.github.com/repos/yahoo/squidb/git/commits{/sha}","comments_url":"https://api.github.com/repos/yahoo/squidb/comments{/number}","issue_comment_url":"https://api.github.com/repos/yahoo/squidb/issues/comments{/number}","contents_url":"https://api.github.com/repos/yahoo/squidb/contents/{+path}","compare_url":"https://api.github.com/repos/yahoo/squidb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yahoo/squidb/merges","archive_url":"https://api.github.com/repos/yahoo/squidb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yahoo/squidb/downloads","issues_url":"https://api.github.com/repos/yahoo/squidb/issues{/number}","pulls_url":"https://api.github.com/repos/yahoo/squidb/pulls{/number}","milestones_url":"https://api.github.com/repos/yahoo/squidb/milestones{/number}","notifications_url":"https://api.github.com/repos/yahoo/squidb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yahoo/squidb/labels{/name}","releases_url":"https://api.github.com/repos/yahoo/squidb/releases{/id}","created_at":"2015-04-15T16:54:33Z","updated_at":"2015-09-08T19:18:36Z","pushed_at":"2015-08-30T16:12:02Z","git_url":"git://github.com/yahoo/squidb.git","ssh_url":"git@github.com:yahoo/squidb.git","clone_url":"https://github.com/yahoo/squidb.git","svn_url":"https://github.com/yahoo/squidb","homepage":"https://github.com/yahoo/squidb/wiki","size":21916,"stargazers_count":958,"watchers_count":958,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":84,"mirror_url":null,"open_issues_count":8,"forks":84,"open_issues":8,"watchers":958,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/83"},"html":{"href":"https://github.com/yahoo/squidb/pull/83"},"issue":{"href":"https://api.github.com/repos/yahoo/squidb/issues/83"},"comments":{"href":"https://api.github.com/repos/yahoo/squidb/issues/83/comments"},"review_comments":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/83/comments"},"review_comment":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/yahoo/squidb/pulls/83/commits"},"statuses":{"href":"https://api.github.com/repos/yahoo/squidb/statuses/bf85eed1e922a4c9ddc43542ed130b8520966aa7"}}}}