{"action":"created","comment":{"url":"https://api.github.com/repos/googleads/aw-reporting/pulls/comments/46867291","id":46867291,"diff_hunk":"@@ -345,4 +358,190 @@ public void setPersister(EntityPersister persister) {\n   public void setAuthentication(Authenticator authenticator) {\n     this.authenticator = authenticator;\n   }\n-}\n+  \n+  @Autowired\n+  public void setReportDefinitionDownloader(ReportDefinitionDownloader reportDefinitionDownloader) {\n+    this.reportDefinitionDownloader = reportDefinitionDownloader;\n+  }\n+  \n+  /**\n+   * Check reports' Java entity classes against ReportDefinitionService,\n+   * and print info/warn/error in the log.\n+   */\n+  public void checkReportEntityClasses(String mccAccountId)\n+      throws OAuthException, ValidationException\n+  {\n+    AdWordsSession session = authenticator.authenticate(mccAccountId, false).build();\n+    this.reportDefinitionDownloader.init(session);\n+    \n+    checkMissingReportTypes();\n+    checkReportFields();\n+  }\n+  \n+  /**\n+   * Check for report types that don't have Jave entity classes\n+   */\n+  private void checkMissingReportTypes() {\n+    Set<ReportDefinitionReportType> definedReports = csvReportEntitiesMapping.getDefinedReports();\n+    List<ReportDefinitionReportType> allReports = new ArrayList<ReportDefinitionReportType>(\n+        Arrays.asList(ReportDefinitionReportType.values()));\n+    allReports.remove(ReportDefinitionReportType.UNKNOWN);\n+    allReports.removeAll(definedReports);\n+    \n+    if (allReports.isEmpty()) {\n+      LOGGER.info(\"Pass! Every report type has a corresponding entity class!\");\n+    } else {\n+      LOGGER.error(\"Missing Java entity classes of \" + allReports.size() + \" report types: \"\n+          + StringUtils.join(allReports, \", \"));\n+    }\n+  }\n+  \n+  /**\n+   * Check for:\n+   * 1. missing/extra report fields\n+   * 2. wrong display field names\n+   * 3. wrong @MoneyField annotation\n+   * 4. wrong Java class member types\n+   */\n+  private void checkReportFields() {\n+    for (ReportDefinitionReportType reportType : csvReportEntitiesMapping.getDefinedReports()) {\n+      final String reportTypeName = reportType.name();\n+      \n+      ReportDefinitionFieldsMap reportDefinitionData = null;\n+      try {\n+        reportDefinitionData = reportDefinitionDownloader.getReportDefinitionFieldsMap(reportType);\n+      } catch (ApiException e) {}\n+      if (reportDefinitionData == null) {\n+        LOGGER.error(\"Cannot get report definition data for \" + reportTypeName);\n+        continue;\n+      }\n+      \n+      Map<String, ReportClassFieldData> reportClassFieldsMap\n+          = getReportClassFieldsMap(reportType, reportDefinitionData);\n+      if (reportClassFieldsMap == null) {\n+        LOGGER.error(\"Cannot find entity class of report \" + reportTypeName);\n+        continue;\n+      }\n+      \n+      Set<String> reportDefinedFieldNames = reportDefinitionData.getFieldNames();\n+      Set<String> reportDeclaredFieldNames = reportClassFieldsMap.keySet();\n+      \n+      // Check missing/extra report fields\n+      Set<String> missingFields = new HashSet<String>(reportDefinedFieldNames);\n+      missingFields.removeAll(reportDeclaredFieldNames);\n+      if (missingFields.isEmpty()) {\n+        LOGGER.info(\"No missing fields found for report \" + reportTypeName);\n+      } else {\n+        LOGGER.error(\"Found missing fields for report \" + reportTypeName + \": \"\n+            + StringUtils.join(missingFields, \", \"));\n+      }\n+      \n+      Set<String> extraFields = new HashSet<String>(reportDeclaredFieldNames);\n+      extraFields.removeAll(reportDefinedFieldNames);\n+      if (extraFields.isEmpty()) {\n+        LOGGER.info(\"No extra fields found for report \" + reportTypeName);\n+      } else {\n+        LOGGER.error(\"Found extra fields for report \" + reportTypeName + \": \"\n+            + StringUtils.join(extraFields, \", \"));\n+      }\n+      \n+      // Check wrong display field names, MoneyField annotations and field types\n+      List<ReportClassFieldData> wrongDisplayNameFields = new ArrayList<ReportClassFieldData>();\n+      List<ReportClassFieldData> wrongMoneyFields = new ArrayList<ReportClassFieldData>();\n+      List<ReportClassFieldData> wrongTypeFields = new ArrayList<ReportClassFieldData>();\n+      \n+      // Use intersection of field names to conduct check\n+      Set<String> fieldNames = new HashSet<String>(reportDeclaredFieldNames);\n+      fieldNames.retainAll(reportDefinedFieldNames);\n+      \n+      for (String fieldName : fieldNames) {\n+        ReportClassFieldData fieldData = reportClassFieldsMap.get(fieldName);\n+        \n+        // Check for wrong display names\n+        if (!fieldData.checkMatchedDisplayName()) {\n+          wrongDisplayNameFields.add(fieldData);\n+        }\n+        \n+        // Check for wrong MoneyField annotations\n+        if (!fieldData.checkMatchedMoneyType()) {\n+          wrongMoneyFields.add(fieldData);\n+        }        \n+        \n+        // Check for wrong types\n+        if (!fieldData.checkFieldType()) {\n+          wrongTypeFields.add(fieldData);\n+        }\n+      }\n+      \n+      if (wrongDisplayNameFields.isEmpty()) {\n+        LOGGER.info(\"All fields' display names are correct for report \" + reportTypeName);\n+      } else {\n+        LOGGER.error(\"The following fields' display names are wrong for report \"\n+            + reportTypeName + \":\");\n+        for (ReportClassFieldData fieldData : wrongDisplayNameFields) {\n+          LOGGER.error(\"  \" + fieldData.getFieldName() + \": (actual) \"\n+              + fieldData.getDeclaredDisplayName() + \", (expected) \"\n+              + fieldData.getDefinedDisplayName());\n+        }\n+      }\n+      \n+      if (wrongMoneyFields.isEmpty()) {\n+        LOGGER.info(\"All @MoneyField annotations are correct for report \" + reportTypeName);\n+      } else {\n+        LOGGER.error(\"The following fields' @MoneyField annotations are wrong for report \"\n+            + reportTypeName + \":\");\n+        for (ReportClassFieldData fieldData : wrongDisplayNameFields) {\n+          LOGGER.error(\"  \" + fieldData.getFieldName() + \": (actual) \"\n+              + fieldData.getDeclaredMoneyField() + \", (expected) \"\n+              + fieldData.getDefinedMoneyField());\n+        }\n+      }\n+      \n+      if (wrongTypeFields.isEmpty()) {\n+        LOGGER.info(\"All fields' types are correct for report \" + reportTypeName);\n+      } else {\n+        LOGGER.error(\"The following fields' types are wrong for report \"\n+            + reportTypeName + \":\");\n+        for (ReportClassFieldData fieldData : wrongTypeFields) {\n+          LOGGER.error(\"  \" + fieldData.getFieldName() + \": (actual) \"\n+              + fieldData.getDeclaredTypeName() + \", (expected) \"\n+              + fieldData.getDefinedTypeName());\n+        }\n+      }\n+    }\n+  }\n+  \n+  /*\n+   * Get the field name -> ReportClassFieldData mapping from declared fields in Java entity class\n+   */\n+  private Map<String, ReportClassFieldData> getReportClassFieldsMap(\n+      ReportDefinitionReportType reportType, ReportDefinitionFieldsMap rdfMap) {\n+    \n+    Class<?> reportClass = csvReportEntitiesMapping.getReportBeanClass(reportType);\n+    if (reportClass == null) {\n+      reportClass = csvReportEntitiesMapping.getExperimentalReportBeanClass(reportType.name());\n+    }\n+    if (reportClass == null) {\n+      return null;\n+    }\n+    \n+    Map<String, ReportClassFieldData> rcfMap = new HashMap<String, ReportClassFieldData>();\n+    \n+    Class<?> curReportClass = reportClass;\n+    while (curReportClass != Object.class) {\n+      for (Field field : curReportClass.getDeclaredFields()) {            ","path":"aw-reporting/src/main/java/com/google/api/ads/adwords/awreporting/processors/ReportProcessor.java","position":219,"original_position":219,"commit_id":"91513994a564d60efb13b3a1f7bef51953f97ae4","original_commit_id":"91513994a564d60efb13b3a1f7bef51953f97ae4","user":{"login":"allisongreene","id":14004396,"avatar_url":"https://avatars.githubusercontent.com/u/14004396?v=3","gravatar_id":"","url":"https://api.github.com/users/allisongreene","html_url":"https://github.com/allisongreene","followers_url":"https://api.github.com/users/allisongreene/followers","following_url":"https://api.github.com/users/allisongreene/following{/other_user}","gists_url":"https://api.github.com/users/allisongreene/gists{/gist_id}","starred_url":"https://api.github.com/users/allisongreene/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allisongreene/subscriptions","organizations_url":"https://api.github.com/users/allisongreene/orgs","repos_url":"https://api.github.com/users/allisongreene/repos","events_url":"https://api.github.com/users/allisongreene/events{/privacy}","received_events_url":"https://api.github.com/users/allisongreene/received_events","type":"User","site_admin":false},"body":"This may also flag some fields that are incorrectly in the base classes.  Is that intended or added bonus :)","created_at":"2015-12-07T19:47:50Z","updated_at":"2015-12-07T19:47:50Z","html_url":"https://github.com/googleads/aw-reporting/pull/213#discussion_r46867291","pull_request_url":"https://api.github.com/repos/googleads/aw-reporting/pulls/213","_links":{"self":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/comments/46867291"},"html":{"href":"https://github.com/googleads/aw-reporting/pull/213#discussion_r46867291"},"pull_request":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/213"}}},"pull_request":{"url":"https://api.github.com/repos/googleads/aw-reporting/pulls/213","id":52832471,"html_url":"https://github.com/googleads/aw-reporting/pull/213","diff_url":"https://github.com/googleads/aw-reporting/pull/213.diff","patch_url":"https://github.com/googleads/aw-reporting/pull/213.patch","issue_url":"https://api.github.com/repos/googleads/aw-reporting/issues/213","number":213,"state":"open","locked":false,"title":"New option \"-checkEntityClasses\" to check all fields of every Java entity class against ReportDefinitionService","user":{"login":"chenzhuo914","id":7360332,"avatar_url":"https://avatars.githubusercontent.com/u/7360332?v=3","gravatar_id":"","url":"https://api.github.com/users/chenzhuo914","html_url":"https://github.com/chenzhuo914","followers_url":"https://api.github.com/users/chenzhuo914/followers","following_url":"https://api.github.com/users/chenzhuo914/following{/other_user}","gists_url":"https://api.github.com/users/chenzhuo914/gists{/gist_id}","starred_url":"https://api.github.com/users/chenzhuo914/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenzhuo914/subscriptions","organizations_url":"https://api.github.com/users/chenzhuo914/orgs","repos_url":"https://api.github.com/users/chenzhuo914/repos","events_url":"https://api.github.com/users/chenzhuo914/events{/privacy}","received_events_url":"https://api.github.com/users/chenzhuo914/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-12-07T11:20:04Z","updated_at":"2015-12-07T19:47:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a4d1a4a8f58633e8597de530d5b912ef481d1586","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/googleads/aw-reporting/pulls/213/commits","review_comments_url":"https://api.github.com/repos/googleads/aw-reporting/pulls/213/comments","review_comment_url":"https://api.github.com/repos/googleads/aw-reporting/pulls/comments{/number}","comments_url":"https://api.github.com/repos/googleads/aw-reporting/issues/213/comments","statuses_url":"https://api.github.com/repos/googleads/aw-reporting/statuses/91513994a564d60efb13b3a1f7bef51953f97ae4","head":{"label":"googleads:rds-optimize","ref":"rds-optimize","sha":"91513994a564d60efb13b3a1f7bef51953f97ae4","user":{"login":"googleads","id":4551618,"avatar_url":"https://avatars.githubusercontent.com/u/4551618?v=3","gravatar_id":"","url":"https://api.github.com/users/googleads","html_url":"https://github.com/googleads","followers_url":"https://api.github.com/users/googleads/followers","following_url":"https://api.github.com/users/googleads/following{/other_user}","gists_url":"https://api.github.com/users/googleads/gists{/gist_id}","starred_url":"https://api.github.com/users/googleads/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googleads/subscriptions","organizations_url":"https://api.github.com/users/googleads/orgs","repos_url":"https://api.github.com/users/googleads/repos","events_url":"https://api.github.com/users/googleads/events{/privacy}","received_events_url":"https://api.github.com/users/googleads/received_events","type":"Organization","site_admin":false},"repo":{"id":13736359,"name":"aw-reporting","full_name":"googleads/aw-reporting","owner":{"login":"googleads","id":4551618,"avatar_url":"https://avatars.githubusercontent.com/u/4551618?v=3","gravatar_id":"","url":"https://api.github.com/users/googleads","html_url":"https://github.com/googleads","followers_url":"https://api.github.com/users/googleads/followers","following_url":"https://api.github.com/users/googleads/following{/other_user}","gists_url":"https://api.github.com/users/googleads/gists{/gist_id}","starred_url":"https://api.github.com/users/googleads/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googleads/subscriptions","organizations_url":"https://api.github.com/users/googleads/orgs","repos_url":"https://api.github.com/users/googleads/repos","events_url":"https://api.github.com/users/googleads/events{/privacy}","received_events_url":"https://api.github.com/users/googleads/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/googleads/aw-reporting","description":"AdWords Reports to DB","fork":false,"url":"https://api.github.com/repos/googleads/aw-reporting","forks_url":"https://api.github.com/repos/googleads/aw-reporting/forks","keys_url":"https://api.github.com/repos/googleads/aw-reporting/keys{/key_id}","collaborators_url":"https://api.github.com/repos/googleads/aw-reporting/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/googleads/aw-reporting/teams","hooks_url":"https://api.github.com/repos/googleads/aw-reporting/hooks","issue_events_url":"https://api.github.com/repos/googleads/aw-reporting/issues/events{/number}","events_url":"https://api.github.com/repos/googleads/aw-reporting/events","assignees_url":"https://api.github.com/repos/googleads/aw-reporting/assignees{/user}","branches_url":"https://api.github.com/repos/googleads/aw-reporting/branches{/branch}","tags_url":"https://api.github.com/repos/googleads/aw-reporting/tags","blobs_url":"https://api.github.com/repos/googleads/aw-reporting/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/googleads/aw-reporting/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/googleads/aw-reporting/git/refs{/sha}","trees_url":"https://api.github.com/repos/googleads/aw-reporting/git/trees{/sha}","statuses_url":"https://api.github.com/repos/googleads/aw-reporting/statuses/{sha}","languages_url":"https://api.github.com/repos/googleads/aw-reporting/languages","stargazers_url":"https://api.github.com/repos/googleads/aw-reporting/stargazers","contributors_url":"https://api.github.com/repos/googleads/aw-reporting/contributors","subscribers_url":"https://api.github.com/repos/googleads/aw-reporting/subscribers","subscription_url":"https://api.github.com/repos/googleads/aw-reporting/subscription","commits_url":"https://api.github.com/repos/googleads/aw-reporting/commits{/sha}","git_commits_url":"https://api.github.com/repos/googleads/aw-reporting/git/commits{/sha}","comments_url":"https://api.github.com/repos/googleads/aw-reporting/comments{/number}","issue_comment_url":"https://api.github.com/repos/googleads/aw-reporting/issues/comments{/number}","contents_url":"https://api.github.com/repos/googleads/aw-reporting/contents/{+path}","compare_url":"https://api.github.com/repos/googleads/aw-reporting/compare/{base}...{head}","merges_url":"https://api.github.com/repos/googleads/aw-reporting/merges","archive_url":"https://api.github.com/repos/googleads/aw-reporting/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/googleads/aw-reporting/downloads","issues_url":"https://api.github.com/repos/googleads/aw-reporting/issues{/number}","pulls_url":"https://api.github.com/repos/googleads/aw-reporting/pulls{/number}","milestones_url":"https://api.github.com/repos/googleads/aw-reporting/milestones{/number}","notifications_url":"https://api.github.com/repos/googleads/aw-reporting/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/googleads/aw-reporting/labels{/name}","releases_url":"https://api.github.com/repos/googleads/aw-reporting/releases{/id}","created_at":"2013-10-21T08:09:32Z","updated_at":"2015-12-05T03:48:41Z","pushed_at":"2015-12-07T18:43:57Z","git_url":"git://github.com/googleads/aw-reporting.git","ssh_url":"git@github.com:googleads/aw-reporting.git","clone_url":"https://github.com/googleads/aw-reporting.git","svn_url":"https://github.com/googleads/aw-reporting","homepage":null,"size":5755,"stargazers_count":61,"watchers_count":61,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":42,"mirror_url":null,"open_issues_count":10,"forks":42,"open_issues":10,"watchers":61,"default_branch":"master"}},"base":{"label":"googleads:master","ref":"master","sha":"6f51fc612c5ade34425873b67a69fe38db20786e","user":{"login":"googleads","id":4551618,"avatar_url":"https://avatars.githubusercontent.com/u/4551618?v=3","gravatar_id":"","url":"https://api.github.com/users/googleads","html_url":"https://github.com/googleads","followers_url":"https://api.github.com/users/googleads/followers","following_url":"https://api.github.com/users/googleads/following{/other_user}","gists_url":"https://api.github.com/users/googleads/gists{/gist_id}","starred_url":"https://api.github.com/users/googleads/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googleads/subscriptions","organizations_url":"https://api.github.com/users/googleads/orgs","repos_url":"https://api.github.com/users/googleads/repos","events_url":"https://api.github.com/users/googleads/events{/privacy}","received_events_url":"https://api.github.com/users/googleads/received_events","type":"Organization","site_admin":false},"repo":{"id":13736359,"name":"aw-reporting","full_name":"googleads/aw-reporting","owner":{"login":"googleads","id":4551618,"avatar_url":"https://avatars.githubusercontent.com/u/4551618?v=3","gravatar_id":"","url":"https://api.github.com/users/googleads","html_url":"https://github.com/googleads","followers_url":"https://api.github.com/users/googleads/followers","following_url":"https://api.github.com/users/googleads/following{/other_user}","gists_url":"https://api.github.com/users/googleads/gists{/gist_id}","starred_url":"https://api.github.com/users/googleads/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/googleads/subscriptions","organizations_url":"https://api.github.com/users/googleads/orgs","repos_url":"https://api.github.com/users/googleads/repos","events_url":"https://api.github.com/users/googleads/events{/privacy}","received_events_url":"https://api.github.com/users/googleads/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/googleads/aw-reporting","description":"AdWords Reports to DB","fork":false,"url":"https://api.github.com/repos/googleads/aw-reporting","forks_url":"https://api.github.com/repos/googleads/aw-reporting/forks","keys_url":"https://api.github.com/repos/googleads/aw-reporting/keys{/key_id}","collaborators_url":"https://api.github.com/repos/googleads/aw-reporting/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/googleads/aw-reporting/teams","hooks_url":"https://api.github.com/repos/googleads/aw-reporting/hooks","issue_events_url":"https://api.github.com/repos/googleads/aw-reporting/issues/events{/number}","events_url":"https://api.github.com/repos/googleads/aw-reporting/events","assignees_url":"https://api.github.com/repos/googleads/aw-reporting/assignees{/user}","branches_url":"https://api.github.com/repos/googleads/aw-reporting/branches{/branch}","tags_url":"https://api.github.com/repos/googleads/aw-reporting/tags","blobs_url":"https://api.github.com/repos/googleads/aw-reporting/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/googleads/aw-reporting/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/googleads/aw-reporting/git/refs{/sha}","trees_url":"https://api.github.com/repos/googleads/aw-reporting/git/trees{/sha}","statuses_url":"https://api.github.com/repos/googleads/aw-reporting/statuses/{sha}","languages_url":"https://api.github.com/repos/googleads/aw-reporting/languages","stargazers_url":"https://api.github.com/repos/googleads/aw-reporting/stargazers","contributors_url":"https://api.github.com/repos/googleads/aw-reporting/contributors","subscribers_url":"https://api.github.com/repos/googleads/aw-reporting/subscribers","subscription_url":"https://api.github.com/repos/googleads/aw-reporting/subscription","commits_url":"https://api.github.com/repos/googleads/aw-reporting/commits{/sha}","git_commits_url":"https://api.github.com/repos/googleads/aw-reporting/git/commits{/sha}","comments_url":"https://api.github.com/repos/googleads/aw-reporting/comments{/number}","issue_comment_url":"https://api.github.com/repos/googleads/aw-reporting/issues/comments{/number}","contents_url":"https://api.github.com/repos/googleads/aw-reporting/contents/{+path}","compare_url":"https://api.github.com/repos/googleads/aw-reporting/compare/{base}...{head}","merges_url":"https://api.github.com/repos/googleads/aw-reporting/merges","archive_url":"https://api.github.com/repos/googleads/aw-reporting/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/googleads/aw-reporting/downloads","issues_url":"https://api.github.com/repos/googleads/aw-reporting/issues{/number}","pulls_url":"https://api.github.com/repos/googleads/aw-reporting/pulls{/number}","milestones_url":"https://api.github.com/repos/googleads/aw-reporting/milestones{/number}","notifications_url":"https://api.github.com/repos/googleads/aw-reporting/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/googleads/aw-reporting/labels{/name}","releases_url":"https://api.github.com/repos/googleads/aw-reporting/releases{/id}","created_at":"2013-10-21T08:09:32Z","updated_at":"2015-12-05T03:48:41Z","pushed_at":"2015-12-07T18:43:57Z","git_url":"git://github.com/googleads/aw-reporting.git","ssh_url":"git@github.com:googleads/aw-reporting.git","clone_url":"https://github.com/googleads/aw-reporting.git","svn_url":"https://github.com/googleads/aw-reporting","homepage":null,"size":5755,"stargazers_count":61,"watchers_count":61,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":42,"mirror_url":null,"open_issues_count":10,"forks":42,"open_issues":10,"watchers":61,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/213"},"html":{"href":"https://github.com/googleads/aw-reporting/pull/213"},"issue":{"href":"https://api.github.com/repos/googleads/aw-reporting/issues/213"},"comments":{"href":"https://api.github.com/repos/googleads/aw-reporting/issues/213/comments"},"review_comments":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/213/comments"},"review_comment":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/googleads/aw-reporting/pulls/213/commits"},"statuses":{"href":"https://api.github.com/repos/googleads/aw-reporting/statuses/91513994a564d60efb13b3a1f7bef51953f97ae4"}}}}