[
  {
    "path": ".gitignore",
    "content": "target/\npom.xml.tag\npom.xml.releaseBackup\npom.xml.versionsBackup\npom.xml.next\nrelease.properties\ndependency-reduced-pom.xml\n\n*.iml\n.idea/\n\n*.class\n"
  },
  {
    "path": "Changelog.adoc",
    "content": "= Changelog\nSebastian Daschner\n\n// new versions are placed on the top\n\n== v0.18 SNAPSHOT\n\n== v0.17\n- Markdown support\n- Added resource description in remaining backends\n- Support to ignore JAX-RS boundary classes\n- fixed minor JavaDoc issues\n\n== v0.16\n- Added AsciiDoc prettification\n- Fixed error on empty application path\n- Minor fixes\n\n== v0.15\n- Fixed JavaDoc erased types\n\n== v0.14\n- Fixed test related execution phase\n\n== v0.13\n- Improved class loading functionality while analyzing\n- Support empty domain (https://github.com/sdaschner/jaxrs-analyzer/issues/42[#42^])\n- Output dir is now editable in maven plugin (https://github.com/sdaschner/jaxrs-analyzer-maven-plugin/issues/13[#13^])\n- Ignore properties in representations via Jackson annotations (https://github.com/sdaschner/jaxrs-analyzer/issues/87[#87^])\n\n== v0.12\n- Fixed JavaDoc related class loading\n\n== v0.11\n- Added JavaDoc analysis for JAX-RS resources\n- Added backend SPI\n- Improved path parameter resolution for extended path regexes\n- Fixed local variable analysis for corner cases\n\n== v0.10\n- Changed internals to ASM\n- Improved type analysis\n- Improved analysis of POJO type inheritance\n- Supported Swagger tags\n- Added option to change Swagger schemes\n- Supported `@DefaultValue`\n- Improved entity body support for \"`Stringifiable`\" types\n- Changed Swagger output to pretty printed JSON\n\n== v0.9\n- Enhanced type resolution for generic types and generic methods\n- Improved Swagger type output\n- Added actual type names to Swagger output\n- Sorted Swagger JSON\n\n== v0.8\n- Improved type resolution for type arguments\n- Fixed errors in swagger specification\n- Fixed Maven plugin error on missing Java EE 7 dependency\n\n== v0.7\n- Restructured Java type representation\n- Improved type resolution for nested JSR-353 calls\n- Improved type analysis for nested & recursive types & methods\n- Improved method resolution on inherited types\n- Fixed CLI calls with relative paths\n\n== v0.6\n- Fixed class loading issue on Windows systems\n- Fixed potential error on invoke interface in nested methods\n- Added type workaround for Map request / response body types\n- Fixed potential error when using `Stream#collect`\n\n== v0.5\n- Improved handling of abstract JAX-RS methods\n- Added more functionality to the CLI tool (e.g. ability to specify several class paths)\n- Changed CLI tool interface to convenient Unix-style parameters\n- Added more log information -- especially on debug level\n\n== v0.4\n- Added AsciiDoc backend\n- Improved variable type resolution\n- Added WebApplicationException handling (thrown WAE's in the code are recognized for the result)\n- Improved `void` method analysis\n- Added project information (name, version, etc.) to backends\n\n== v0.3\n- Improved POJO getter analysis for return types (e.g. isXY() -> boolean, etc.)\n- Added JDK 1.8 Streams as known methods (analysis will notice and simulate these)\n- Improved JAXB analysis of POJOs (all `XmlAccessorType's`, `XmlElement` and `XmlTransient` supported)\n\n== v0.2\n- Minor updated needed for Sonatype release\n\n== v0.1\n- JAX-RS 2.0 annotations analysis\n- `Response` return types analysis (determines where the returned objects ``come from'', follows method invocations, actual arguments, etc.)\n- JSON-P API analysis (e.g. methods with return type `JsonObject` or JSON-P contained in `Response#entity()`)\n- Analysis of POJO responses\n- JAXB analysis of POJOs (only `XmlAccessorType#PUBLIC_MEMBER`)\n- JDK 1.8 lambdas analysis\n- Swagger API JSON backend format\n- Plain text backend format\n"
  },
  {
    "path": "Documentation.adoc",
    "content": "= JAX-RS Analyzer\nSebastian Daschner\n\nThe JAX-RS Analyzer generates an overview of all JAX-RS resources in a JavaEE project.\nBesides other approaches this tool uses Bytecode analysis to maximise the extracted information.\n\nThe Analyzer is available as https://github.com/sdaschner/jaxrs-analyzer-maven-plugin/[Maven plugin] or standalone version (executable jar file).\n\n== Quickstart (tl;dr)\nJust add the latest release version of the JAX-RS Analyzer to your Maven pom.xml in the `<plugins>`-section:\n\n----\n<plugin>\n    <groupId>com.sebastian-daschner</groupId>\n    <artifactId>jaxrs-analyzer-maven-plugin</artifactId>\n    <version>0.17</version>\n    <executions>\n        <execution>\n            <goals>\n                <goal>analyze-jaxrs</goal>\n            </goals>\n            <configuration>\n                <backend>swagger</backend>\n            </configuration>\n        </execution>\n    </executions>\n</plugin>\n----\n\nFor an introductional video see https://blog.sebastian-daschner.com/entries/jaxrs_analyzer_explained_video[JAX-RS Analyzer explained (Video)].\n\n== Maven Plugin\nPlease see the https://github.com/sdaschner/jaxrs-analyzer-maven-plugin[Maven plugin project] and a https://github.com/sdaschner/jaxrs-analyzer-maven-plugin/blob/master/Documentation.adoc[documentation] of all parameters.\n\n== Standalone\nInstead of using the Maven plugin, the tool can also run directly from the jar file.\n\nYou can download the latest version https://github.com/sdaschner/jaxrs-analyzer/releases[here].\nAlternatively the executable can be build with `mvn clean install`.\n\nRun the jar file with `java -jar jaxrs-analyzer.jar [options] <projectPathToCompiledClasses> [projectPathToCompiledClasses...]`, e.g. `java -jar jaxrs-analyzer.jar -b swagger ../yourProject/target/classes`.\n\nThe `projectPath` entries may be directories or jar files containing the classes to be analyzed.\n\nFollowing available options:\n\n* `-b <backend>` The backend to choose: `swagger` (default), `plaintext`, `asciidoc`, `markdown`\n* `-cp <class path>[:class paths...]` The additional class paths containing classes which are used in the project (separated by colon); this may be directories or jar-files\n* `-X` Debug enabled (prints error debugging information on Standard error out)\n* `-n <project name>` The name of the project\n* `-v <project version>` The version of the project\n* `-d <project domain>` The domain of the project\n* `-o <output file>` The location of the analysis output (will be printed to standard out if omitted)\n\nFollowing available backend specific options (only have effect if the corresponding backend is selected):\n\n* `--swaggerSchemes <scheme>[,schemes]` The Swagger schemes: `http` (default), `https`, `ws`, `wss`\n* `--renderSwaggerTags` Enables rendering of Swagger tags (default tag will be used per default)\n* `--swaggerTagsPathOffset <path offset>` The number at which path position the Swagger tags will be extracted (0 will be used per default)\n* `--ignoredRootResources <fully qualified classname [class,...]>` JAX-RS root resource classes which should be ignored by analyze (empty per default). Note that these ignores only cause the classes to be ignored as root resources; they might still be taken into account as JAX-RS sub-resources.\n\n== Backends\nThe Analyzer supports Plaintext, AsciiDoc, Markdown and Swagger as output format.\nThe latter three can be processed further.\n\nAsciiDoc and Markdown are human-readable, lightweight markup languages.\nThey can easily converted to PDF, HTML, and many more.\n\nThe Swagger JSON file can be used with Swagger UI or the http://editor.swagger.io[Swagger Editor].\n\n Swagger UI is a dependency-free collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.\n\n== Changelog\nFor the latest changes see the https://github.com/sdaschner/jaxrs-analyzer/blob/master/Changelog.adoc[Changelog].\n\n== Contributing\nFeedback, bug reports and ideas for improvement are very welcome! Feel free to fork, comment, file an issue, etc. ;-)\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2015 Sebastian Daschner\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "README.adoc",
    "content": "= JAX-RS Analyzer\nSebastian Daschner\n\nGenerates an overview of all JAX-RS resources in a project by bytecode analysis.\n\n*Yet another such JAX-RS tool?* +\nYes, but this gathers the information about the JAX-RS resource classes by bytecode analysis (not just by reflection).\nThis gains more information in several situations. You don't need additional annotations on your JAX-RS resource methods.\nUsing the JSR 339 standard is sufficient.\n\nJava 8 is needed for the Analyzer.\n\nFor usage see the https://github.com/sdaschner/jaxrs-analyzer/blob/master/Documentation.adoc[documentation].\n\n== Maven Plugin\nThe Analyzer can be added to your project via https://github.com/sdaschner/jaxrs-analyzer-maven-plugin[Maven plugin].\n\n== Gradle Plugin\nFor `Gradle` based projects - third-party https://github.com/grimmjo/jaxrs-analyzer-gradle-plugin[Gradle plugin] could be used.\n\n== Standalone\nInstead of using the Maven plugin, the tool can also run directly from the jar file.\nYou can download the latest version https://github.com/sdaschner/jaxrs-analyzer/releases[here].\n\n== Backends\nThe Analyzer supports Plaintext, AsciiDoc, Markdown and Swagger as output format.\n\n== Documentation / Feature list\n+...+ can be found https://github.com/sdaschner/jaxrs-analyzer/blob/master/Documentation.adoc[here].\n\nFeedback, bug reports and ideas for improvement are very welcome! Feel free to fork, comment, file an issue, etc. ;-)\n"
  },
  {
    "path": "pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.sebastian-daschner</groupId>\n    <artifactId>jaxrs-analyzer</artifactId>\n    <version>0.18-SNAPSHOT</version>\n    <name>JAX-RS Analyzer</name>\n    <packaging>jar</packaging>\n\n    <description>Generates REST documentation by analysing JAX-RS projects.</description>\n    <url>https://github.com/sdaschner/jaxrs-analyzer</url>\n\n    <licenses>\n        <license>\n            <name>The Apache License, Version 2.0</name>\n            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>\n        </license>\n    </licenses>\n\n    <developers>\n        <developer>\n            <name>Sebastian Daschner</name>\n            <organization>sebastian-daschner.com</organization>\n            <organizationUrl>https://www.sebastian-daschner.com</organizationUrl>\n        </developer>\n    </developers>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.glassfish</groupId>\n            <artifactId>javax.json</artifactId>\n            <version>1.1</version>\n        </dependency>\n        <dependency>\n            <groupId>javax</groupId>\n            <artifactId>javaee-api</artifactId>\n            <version>7.0</version>\n        </dependency>\n        <dependency>\n            <groupId>org.ow2.asm</groupId>\n            <artifactId>asm</artifactId>\n            <version>6.2.1</version>\n        </dependency>\n        <dependency>\n            <groupId>org.ow2.asm</groupId>\n            <artifactId>asm-util</artifactId>\n            <version>6.2.1</version>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-annotations</artifactId>\n            <version>2.8.5</version>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <version>4.12</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <version>1.10.19</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>net.jcip</groupId>\n            <artifactId>jcip-annotations</artifactId>\n            <version>1.0</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.github.javaparser</groupId>\n            <artifactId>javaparser-core</artifactId>\n            <version>3.5.3</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <finalName>jaxrs-analyzer</finalName>\n\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-shade-plugin</artifactId>\n                <version>2.4.3</version>\n                <executions>\n                    <execution>\n                        <phase>package</phase>\n                        <goals>\n                            <goal>shade</goal>\n                        </goals>\n                        <configuration>\n                            <transformers>\n                                <transformer implementation=\"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\">\n                                    <mainClass>com.sebastian_daschner.jaxrs_analyzer.Main</mainClass>\n                                </transformer>\n                            </transformers>\n                            <filters>\n                                <filter>\n                                    <artifact>*:*</artifact>\n                                    <excludes>\n                                        <exclude>com/sun/javadoc/**</exclude>\n                                    </excludes>\n                                </filter>\n                            </filters>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <maven.compiler.source>1.8</maven.compiler.source>\n        <maven.compiler.target>1.8</maven.compiler.target>\n        <maven.javadoc.failOnError>false</maven.javadoc.failOnError>\n    </properties>\n\n    <scm>\n        <connection>scm:git:git@github.com:sdaschner/jaxrs-analyzer.git</connection>\n        <developerConnection>scm:git:git@github.com:sdaschner/jaxrs-analyzer.git</developerConnection>\n        <url>scm:git:git@github.com:sdaschner/jaxrs-analyzer.git</url>\n        <tag>HEAD</tag>\n    </scm>\n\n    <distributionManagement>\n        <snapshotRepository>\n            <id>ossrh-snapshots</id>\n            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>\n        </snapshotRepository>\n        <repository>\n            <id>ossrh</id>\n            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>\n        </repository>\n    </distributionManagement>\n\n    <profiles>\n        <profile>\n            <id>release-sign-artifacts</id>\n            <activation>\n                <property>\n                    <name>performRelease</name>\n                    <value>true</value>\n                </property>\n            </activation>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>3.0.1</version>\n                        <executions>\n                            <execution>\n                                <id>attach-sources</id>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>1.6</version>\n                        <executions>\n                            <execution>\n                                <id>sign-artifacts</id>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-release-plugin</artifactId>\n                        <version>2.5.3</version>\n                        <configuration>\n                            <tagNameFormat>v@{project.version}</tagNameFormat>\n                        </configuration>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n\n</project>\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/JAXRSAnalyzer.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.ProjectAnalyzer;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Project;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\n\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.nio.file.Path;\nimport java.util.*;\nimport java.util.stream.StreamSupport;\n\n/**\n * Generates REST documentation of JAX-RS projects automatically by bytecode analysis.\n *\n * @author Sebastian Daschner\n */\npublic class JAXRSAnalyzer {\n\n    private final Analysis analysis;\n\n    /**\n     * Constructs a JAX-RS Analyzer.\n     */\n    public JAXRSAnalyzer(Analysis analysis) {\n        Objects.requireNonNull(analysis);\n        Objects.requireNonNull(analysis.projectClassPaths);\n        Objects.requireNonNull(analysis.projectSourcePaths);\n        Objects.requireNonNull(analysis.classPaths);\n        Objects.requireNonNull(analysis.projectName);\n        Objects.requireNonNull(analysis.projectVersion);\n        Objects.requireNonNull(analysis.backend);\n\n        if (analysis.projectClassPaths.isEmpty())\n            throw new IllegalArgumentException(\"At least one project path is mandatory\");\n\n        this.analysis = analysis;\n    }\n\n    /**\n     * Analyzes the JAX-RS project at the class path and produces the output as configured.\n     */\n    public void analyze() {\n        final Resources resources = new ProjectAnalyzer(analysis.classPaths)\n                .analyze(analysis.projectClassPaths, analysis.projectSourcePaths, analysis.ignoredResources);\n\n        if (resources.isEmpty()) {\n            LogProvider.info(\"Empty JAX-RS analysis result, omitting output\");\n            return;\n        }\n\n        final Project project = new Project(analysis.projectName, analysis.projectVersion, resources);\n        final byte[] output = analysis.backend.render(project);\n\n        if (analysis.outputLocation != null) {\n            outputToFile(output, analysis.outputLocation);\n        } else {\n            outputToConsole(output);\n        }\n    }\n\n    private void outputToConsole(final byte[] output) {\n        try {\n            System.out.write(output);\n            System.out.flush();\n        } catch (IOException e) {\n            LogProvider.error(\"Could not write the output, reason: \" + e.getMessage());\n            LogProvider.debug(e);\n        }\n    }\n\n    private static void outputToFile(final byte[] output, final Path outputLocation) {\n        try (final OutputStream stream = new FileOutputStream(outputLocation.toFile())) {\n            stream.write(output);\n            stream.flush();\n        } catch (IOException e) {\n            LogProvider.error(\"Could not write to the specified output location, reason: \" + e.getMessage());\n            LogProvider.debug(e);\n        }\n    }\n\n    public static Backend constructBackend(final String backendType) {\n        final ServiceLoader<Backend> backends = ServiceLoader.load(Backend.class);\n        return StreamSupport.stream(backends.spliterator(), false)\n                .filter(b -> backendType.equalsIgnoreCase(b.getName()))\n                .findAny()\n                .orElseThrow(() -> new IllegalArgumentException(\"Unknown backend type \" + backendType));\n    }\n\n    public static class Analysis {\n\n        private final Set<Path> projectClassPaths = new HashSet<>();\n        private final Set<Path> projectSourcePaths = new HashSet<>();\n        private final Set<Path> classPaths = new HashSet<>();\n        private final Set<String> ignoredResources = new HashSet<>();\n        private String projectName;\n        private String projectVersion;\n        private Path outputLocation;\n        private Backend backend;\n\n        public Set<Path> getProjectClassPaths() {\n            return projectClassPaths;\n        }\n\n        public void addProjectClassPath(Path classPath) {\n            projectClassPaths.add(classPath);\n        }\n\n        public void addProjectSourcePath(Path sourcePath) {\n            projectSourcePaths.add(sourcePath);\n        }\n\n        public void addClassPath(Path classPath) {\n            classPaths.add(classPath);\n        }\n\n        public void addIgnoredResource(String ignored) {\n            ignoredResources.add(ignored);\n        }\n\n        public void configureBackend(Map<String, String> attributes) {\n            if (backend != null)\n                backend.configure(attributes);\n        }\n\n        public void setProjectName(String projectName) {\n            this.projectName = projectName;\n        }\n\n        public void setProjectVersion(String projectVersion) {\n            this.projectVersion = projectVersion;\n        }\n\n        public void setOutputLocation(Path outputLocation) {\n            this.outputLocation = outputLocation;\n        }\n\n        public void setBackend(Backend backend) {\n            this.backend = backend;\n        }\n\n        public Backend getBackend() {\n            return backend;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/LogProvider.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.function.Consumer;\n\n/**\n * Exposes functionality to replace / retrieve an external logger.\n *\n * @author Sebastian Daschner\n */\npublic final class LogProvider {\n\n    private static Consumer<String> infoLogger = System.err::println;\n    private static Consumer<String> debugLogger = s -> {\n        // do nothing\n    };\n    private static Consumer<String> errorLogger = System.err::println;\n\n    private LogProvider() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Injects an own info logger functionality. Overwrites the previously associated info logger.\n     *\n     * @param logger The new info logger\n     */\n    public static void injectInfoLogger(final Consumer<String> logger) {\n        LogProvider.infoLogger = logger;\n    }\n\n    /**\n     * Injects an own debug logger functionality. Overwrites the previously associated debug logger.\n     *\n     * @param logger The new debug logger\n     */\n    public static void injectDebugLogger(final Consumer<String> logger) {\n        LogProvider.debugLogger = logger;\n    }\n\n    /**\n     * Injects an own error logger functionality. Overwrites the previously associated error logger.\n     *\n     * @param logger The new error logger\n     */\n    public static void injectErrorLogger(final Consumer<String> logger) {\n        LogProvider.errorLogger = logger;\n    }\n\n    /**\n     * Logs a message to the configured info logger.\n     *\n     * @param message The message to log\n     */\n    public static void info(final String message) {\n        infoLogger.accept(message);\n    }\n\n    /**\n     * Logs a message to the configured debug logger.\n     *\n     * @param message The message to log\n     */\n    public static void debug(final String message) {\n        debugLogger.accept(message);\n    }\n\n    /**\n     * Logs the stacktrace of the throwable to the debug logger.\n     *\n     * @param throwable The throwable to log\n     */\n    public static void debug(final Throwable throwable) {\n        final StringWriter errors = new StringWriter();\n        throwable.printStackTrace(new PrintWriter(errors));\n        debugLogger.accept(errors.toString());\n    }\n\n    /**\n     * Logs a message to the configured error logger.\n     *\n     * @param message The message to log\n     */\n    public static void error(final String message) {\n        errorLogger.accept(message);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/Main.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.sebastian_daschner.jaxrs_analyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.swagger.SwaggerOptions;\n\nimport java.io.File;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/**\n * Inspects the information of JAX-RS classes via bytecode analysis.\n *\n * @author Sebastian Daschner\n */\npublic class Main {\n\n    private static final String DEFAULT_NAME = \"project\";\n    private static final String DEFAULT_VERSION = \"0.1-SNAPSHOT\";\n    private static final String DEFAULT_BACKEND = \"swagger\";\n    private static final String COMMA_LIST_SEPARATOR = \",\";\n\n    private static final JAXRSAnalyzer.Analysis analysis = new JAXRSAnalyzer.Analysis();\n    private static final Map<String, String> attributes = new HashMap<>();\n\n    /**\n     * Inspects JAX-RS projects and outputs the gathered information.\n     * <p>\n     * Argument usage: {@code [options] projectPath [projectPaths...]}\n     * <p>\n     * The {@code projectPath} entries may be directories or jar-files containing the classes to be analyzed\n     * <p>\n     * Following available options:\n     * <ul>\n     * <li>{@code -b backend} The backend to choose: {@code swagger} (default), {@code plaintext}, {@code asciidoc}, {@code markdown}</li>\n     * <li>{@code -cp class path[:class paths...]} The additional class paths which contain classes which are used in the project</li>\n     * <li>{@code -sp source path[:source paths...]} The optional source paths  needed for JavaDoc analysis</li>\n     * <li>{@code -X} Debug enabled (prints error debugging information on Standard error out)</li>\n     * <li>{@code -n project name} The name of the project</li>\n     * <li>{@code -v project version} The version of the project</li>\n     * <li>{@code -d project domain} The domain of the project</li>\n     * <li>{@code -o output file} The location of the analysis output (will be printed to standard out if omitted)</li>\n     * <li>{@code -e encoding} The source file encoding</li>\n     * </ul>\n     * <p>\n     * Following available backend specific options (only have effect if the corresponding backend is selected):\n     * <ul>\n     * <li>{@code --swaggerSchemes scheme[,schemes]} The Swagger schemes: {@code http} (default), {@code https}, {@code ws}, {@code wss}\")</li>\n     * <li>{@code --renderSwaggerTags} Enables rendering of Swagger tags (will not be rendered per default)</li>\n     * <li>{@code --swaggerTagsPathOffset path offset} The number at which path position the Swagger tags should be extracted ({@code 0} per default)</li>\n     * <li>{@code --ignoredRootResources class[,classes]} JAX-RS root resource classes which should be ignored by analyze (empty per default)</li>\n     * </ul>\n     *\n     * @param args The arguments\n     */\n    public static void main(final String... args) {\n        if (args.length < 1) {\n            printUsageAndExit();\n        }\n\n        try {\n            setDefaults();\n            extractArgs(args);\n        } catch (IllegalArgumentException e) {\n            System.err.println(e.getMessage() + '\\n');\n            printUsageAndExit();\n        }\n\n        validateArgs();\n        configureBackend();\n\n        new JAXRSAnalyzer(analysis).analyze();\n    }\n\n    private static void setDefaults() {\n        analysis.setProjectName(DEFAULT_NAME);\n        analysis.setProjectVersion(DEFAULT_VERSION);\n    }\n\n    private static void extractArgs(String[] args) {\n        try {\n            for (int i = 0; i < args.length; i++) {\n                if (args[i].startsWith(\"-\")) {\n                    switch (args[i]) {\n                        case \"-b\":\n                            analysis.setBackend(extractBackend(args[++i]));\n                            break;\n                        case \"-cp\":\n                            extractClassPaths(args[++i]).forEach(analysis::addClassPath);\n                            break;\n                        case \"-sp\":\n                            extractClassPaths(args[++i]).forEach(analysis::addProjectSourcePath);\n                            break;\n                        case \"-X\":\n                            LogProvider.injectDebugLogger(System.err::println);\n                            break;\n                        case \"-n\":\n                            analysis.setProjectName(args[++i]);\n                            break;\n                        case \"-v\":\n                            analysis.setProjectVersion(args[++i]);\n                            break;\n                        case \"-d\":\n                            attributes.put(SwaggerOptions.DOMAIN, args[++i]);\n                            break;\n                        case \"-o\":\n                            analysis.setOutputLocation(Paths.get(args[++i]));\n                            break;\n                        case \"-e\":\n                            System.setProperty(\"project.build.sourceEncoding\", args[++i]);\n                            break;\n                        case \"--swaggerSchemes\":\n                            attributes.put(SwaggerOptions.SWAGGER_SCHEMES, args[++i]);\n                            break;\n                        case \"--renderSwaggerTags\":\n                            attributes.put(SwaggerOptions.RENDER_SWAGGER_TAGS, \"true\");\n                            break;\n                        case \"--swaggerTagsPathOffset\":\n                            attributes.put(SwaggerOptions.SWAGGER_TAGS_PATH_OFFSET, args[++i]);\n                            break;\n                        case \"--noInlinePrettify\":\n                            attributes.put(StringBackend.INLINE_PRETTIFY, \"false\");\n                            break;\n                        case \"--ignoredRootResources\":\n                            extractList(args[++i]).forEach(analysis::addIgnoredResource);\n                            break;\n                        case \"-a\":\n                            addAttribute(args[++i]);\n                            break;\n                        default:\n                            throw new IllegalArgumentException(\"Unknown option \" + args[i]);\n                    }\n                } else {\n                    final Path path = Paths.get(args[i].replaceFirst(\"^~\", System.getProperty(\"user.home\")));\n                    if (!path.toFile().exists()) {\n                        System.err.println(\"Location \" + path.toFile() + \" doesn't exist\\n\");\n                        printUsageAndExit();\n                    }\n                    analysis.addProjectClassPath(path);\n                }\n            }\n        } catch (IndexOutOfBoundsException e) {\n            throw new IllegalArgumentException(\"Please provide valid number of arguments\");\n        }\n    }\n\n    static Map<String, String> addAttribute(String attribute) {\n        int separatorIndex = attribute.indexOf('=');\n\n        if (separatorIndex < 0) {\n            attributes.put(attribute, \"\");\n        } else {\n            attributes.put(attribute.substring(0, separatorIndex).trim(), attribute.substring(separatorIndex + 1).trim());\n        }\n\n        return attributes;\n    }\n\n    private static Backend extractBackend(final String name) {\n        return JAXRSAnalyzer.constructBackend(name.toLowerCase());\n    }\n\n    private static List<Path> extractClassPaths(final String classPaths) {\n        final List<Path> paths = Stream.of(classPaths.split(File.pathSeparator))\n                .map(s -> s.replaceFirst(\"^~\", System.getProperty(\"user.home\")))\n                .map(Paths::get).collect(Collectors.toList());\n        paths.forEach(p -> {\n            if (!p.toFile().exists()) {\n                throw new IllegalArgumentException(\"Class path \" + p.toFile() + \" doesn't exist\");\n            }\n        });\n        return paths;\n    }\n\n    private static List<String> extractList(String list) {\n        return Stream.of(list.split(COMMA_LIST_SEPARATOR))\n                .map(String::trim)\n                .filter(item -> !item.isEmpty())\n                .collect(Collectors.toList());\n    }\n\n    private static void validateArgs() {\n        if (analysis.getProjectClassPaths().isEmpty()) {\n            System.err.println(\"Please provide at least one project path\\n\");\n            printUsageAndExit();\n        }\n    }\n\n    private static void configureBackend() {\n        if (analysis.getBackend() == null)\n            analysis.setBackend(JAXRSAnalyzer.constructBackend(DEFAULT_BACKEND));\n        analysis.configureBackend(attributes);\n    }\n\n    private static void printUsageAndExit() {\n        System.err.println(\"Usage: java -jar jaxrs-analyzer.jar [options] classPath [classPaths...]\");\n        System.err.println(\"The classPath entries may be directories or jar-files containing the classes to be analyzed\\n\");\n        System.err.println(\"Following available options:\\n\");\n        System.err.println(\" -b <backend> The backend to choose: swagger (default), plaintext, asciidoc, markdown\");\n        System.err.println(\" -cp <class path>[:class paths] Additional class paths (separated with colon) which contain classes used in the project (may be directories or jar-files)\");\n        System.err.println(\" -sp <source path>[:source paths] Optional source paths (separated with colon) needed for JavaDoc analysis (may be directories or jar-files)\");\n        System.err.println(\" -X Debug enabled (enabled error debugging information)\");\n        System.err.println(\" -n <project name> The name of the project\");\n        System.err.println(\" -v <project version> The version of the project\");\n        System.err.println(\" -d <project domain> The domain of the project\");\n        System.err.println(\" -o <output file> The location of the analysis output (will be printed to standard out if omitted)\");\n        System.err.println(\" -a <attribute name>=<attribute value> Set custom attributes for backends.\");\n        System.err.println(\" -e <encoding> The source file encoding\");\n        System.err.println(\"\\nFollowing available backend specific options (only have effect if the corresponding backend is selected):\\n\");\n        System.err.println(\" --swaggerSchemes <scheme>[,schemes] The Swagger schemes: http (default), https, ws, wss\");\n        System.err.println(\" --renderSwaggerTags Enables rendering of Swagger tags (default tag will be used per default)\");\n        System.err.println(\" --swaggerTagsPathOffset <path offset> The number at which path position the Swagger tags will be extracted (0 will be used per default)\");\n        System.err.println(\" --ignoredRootResources <fully qualified classname [class,...]> JAX-RS root resource classes which should be ignored by analyze (empty per default)\");\n        System.err.println(\" --noPrettyPrint Don't pretty print inline JSON body representations (will be pretty printed per default)\");\n        System.err.println(\"\\nExample: java -jar jaxrs-analyzer.jar -b swagger -n \\\"My Project\\\" -cp ~/libs/lib1.jar:~/libs/project/bin ~/project/target/classes\");\n        System.exit(1);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/JobRegistry.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\n\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\n/**\n * Thread-safe singleton of unhandled class analysis jobs.\n *\n * @author Sebastian Daschner\n */\npublic class JobRegistry {\n\n    private static final JobRegistry INSTANCE = new JobRegistry();\n    private Queue<Pair<String, ClassResult>> unhandledClasses = new ConcurrentLinkedQueue<>();\n\n    private JobRegistry() {\n        // only one instance allowed\n    }\n\n    /**\n     * Adds the (sub-)resource class name to the analysis list with the associated class result.\n     */\n    public void analyzeResourceClass(final String className, final ClassResult classResult) {\n        // TODO check if class has already been analyzed\n        unhandledClasses.add(Pair.of(className, classResult));\n    }\n\n    /**\n     * Returns a class which has not been analyzed yet.\n     *\n     * @return An unhandled class or {@code null} if all classes have been analyzed\n     */\n    public Pair<String, ClassResult> nextUnhandledClass() {\n        return unhandledClasses.poll();\n    }\n\n    public static JobRegistry getInstance() {\n        return INSTANCE;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/ProjectAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.BytecodeAnalyzer;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.JAXRSClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.javadoc.JavaDocAnalyzer;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.ResultInterpreter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\n\nimport javax.ws.rs.ApplicationPath;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.Enumeration;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.jar.JarEntry;\nimport java.util.jar.JarFile;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.isAnnotationPresent;\n\n/**\n * Analyzes the JAX-RS project. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\npublic class ProjectAnalyzer {\n\n    // TODO test following scenario:\n    // 2 Maven modules -> a, b; a needs b\n    // b contains interface with @Path & resource methods\n    // a contains impl of iface without annotations\n    // b should have result\n\n    private final Lock lock = new ReentrantLock();\n    private final Set<String> classes = new HashSet<>();\n    private final ResultInterpreter resultInterpreter = new ResultInterpreter();\n    private final BytecodeAnalyzer bytecodeAnalyzer = new BytecodeAnalyzer();\n    private final JavaDocAnalyzer javaDocAnalyzer = new JavaDocAnalyzer();\n\n    /**\n     * Creates a project analyzer with given class path locations where to search for classes.\n     *\n     * @param classPaths The locations of additional class paths (can be directories or jar-files)\n     */\n    public ProjectAnalyzer(final Set<Path> classPaths) {\n        classPaths.forEach(this::addToClassPool);\n    }\n\n    /**\n     * Analyzes all classes in the given project path.\n     *\n     * @param projectClassPaths  The project class paths\n     * @param projectSourcePaths The project source file paths\n     * @param ignoredResources   The fully-qualified root resource class names to be ignored\n     * @return The REST resource representations\n     */\n    public Resources analyze(Set<Path> projectClassPaths, Set<Path> projectSourcePaths, Set<String> ignoredResources) {\n        lock.lock();\n        try {\n            projectClassPaths.forEach(this::addProjectPath);\n\n            // analyze relevant classes\n            final JobRegistry jobRegistry = JobRegistry.getInstance();\n            final Set<ClassResult> classResults = new HashSet<>();\n\n            classes.stream()\n                    .filter(this::isJAXRSRootResource)\n                    .filter(r -> !ignoredResources.contains(r))\n                    .forEach(c -> jobRegistry.analyzeResourceClass(c, new ClassResult()));\n\n            Pair<String, ClassResult> classResultPair;\n            while ((classResultPair = jobRegistry.nextUnhandledClass()) != null) {\n                final ClassResult classResult = classResultPair.getRight();\n\n                classResults.add(classResult);\n                analyzeClass(classResultPair.getLeft(), classResult);\n\n                bytecodeAnalyzer.analyzeBytecode(classResult);\n            }\n\n            javaDocAnalyzer.analyze(projectSourcePaths, classResults);\n\n            return resultInterpreter.interpret(classResults);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private boolean isJAXRSRootResource(String className) {\n        final Class<?> clazz = JavaUtils.loadClassFromName(className);\n        return clazz != null && (isAnnotationPresent(clazz, javax.ws.rs.Path.class) || isAnnotationPresent(clazz, ApplicationPath.class));\n    }\n\n    private void analyzeClass(final String className, ClassResult classResult) {\n        try {\n            final ClassReader classReader = new ContextClassReader(className);\n            final ClassVisitor visitor = new JAXRSClassVisitor(classResult);\n\n            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n        } catch (IOException e) {\n            LogProvider.error(\"The class \" + className + \" could not be loaded!\");\n            LogProvider.debug(e);\n        }\n    }\n\n    /**\n     * Adds the location to the class pool.\n     *\n     * @param location The location of a jar file or a directory\n     */\n    private void addToClassPool(final Path location) {\n        if (!location.toFile().exists())\n            throw new IllegalArgumentException(\"The location '\" + location + \"' does not exist!\");\n        try {\n            ContextClassReader.addClassPath(location.toUri().toURL());\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"The location '\" + location + \"' could not be loaded to the class path!\", e);\n        }\n    }\n\n    /**\n     * Adds the project paths and loads all classes.\n     *\n     * @param path The project path\n     */\n    private void addProjectPath(final Path path) {\n        addToClassPool(path);\n\n        if (path.toFile().isFile() && path.toString().endsWith(\".jar\")) {\n            addJarClasses(path);\n        } else if (path.toFile().isDirectory()) {\n            addDirectoryClasses(path, Paths.get(\"\"));\n        } else {\n            throw new IllegalArgumentException(\"The project path '\" + path + \"' must be a jar file or a directory\");\n        }\n    }\n\n    /**\n     * Adds all classes in the given jar-file location to the set of known classes.\n     *\n     * @param location The location of the jar-file\n     */\n    private void addJarClasses(final Path location) {\n        try (final JarFile jarFile = new JarFile(location.toFile())) {\n            final Enumeration<JarEntry> entries = jarFile.entries();\n            while (entries.hasMoreElements()) {\n                final JarEntry entry = entries.nextElement();\n                final String entryName = entry.getName();\n                if (entryName.endsWith(\".class\"))\n                    classes.add(toQualifiedClassName(entryName));\n            }\n        } catch (IOException e) {\n            throw new IllegalArgumentException(\"Could not read jar-file '\" + location + \"', reason: \" + e.getMessage());\n        }\n    }\n\n    /**\n     * Adds all classes in the given directory location to the set of known classes.\n     *\n     * @param location The location of the current directory\n     * @param subPath  The sub-path which is relevant for the package names or {@code null} if currently in the root directory\n     */\n    private void addDirectoryClasses(final Path location, final Path subPath) {\n        for (final File file : location.toFile().listFiles()) {\n            if (file.isDirectory())\n                addDirectoryClasses(location.resolve(file.getName()), subPath.resolve(file.getName()));\n            else if (file.isFile() && file.getName().endsWith(\".class\")) {\n                final String classFileName = subPath.resolve(file.getName()).toString();\n                classes.add(toQualifiedClassName(classFileName));\n            }\n        }\n    }\n\n    /**\n     * Converts the given file name of a class-file to the fully-qualified class name.\n     *\n     * @param fileName The file name (e.g. a/package/AClass.class)\n     * @return The fully-qualified class name (e.g. a.package.AClass)\n     */\n    private static String toQualifiedClassName(final String fileName) {\n        final String replacedSeparators = fileName.replace(File.separatorChar, '.');\n        return replacedSeparators.substring(0, replacedSeparators.length() - \".class\".length());\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/BytecodeAnalyzer.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\n/**\n * @author Sebastian Daschner\n */\npublic class BytecodeAnalyzer {\n\n    private final ResourceMethodContentAnalyzer methodContentAnalyzer = new ResourceMethodContentAnalyzer();\n    private final SubResourceLocatorMethodContentAnalyzer subResourceLocatorAnalyzer = new SubResourceLocatorMethodContentAnalyzer();\n\n    /**\n     * Analyzes the bytecode instructions of the method results and interprets JAX-RS relevant information.\n     */\n    public void analyzeBytecode(final ClassResult classResult) {\n        classResult.getMethods().forEach(this::analyzeBytecode);\n    }\n\n    private void analyzeBytecode(final MethodResult methodResult) {\n        if (methodResult.getHttpMethod() == null) {\n            // sub-resource\n            subResourceLocatorAnalyzer.analyze(methodResult);\n        } else {\n            methodContentAnalyzer.analyze(methodResult);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/MethodContentAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.RelevantInstructionReducer;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ProjectMethodClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.InvokeInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\n\nimport java.io.IOException;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\n/**\n * Analyzes the content of a method. Sub classes have to be thread-safe.\n *\n * @author Sebastian Daschner\n */\nabstract class MethodContentAnalyzer {\n\n    /**\n     * The number of package hierarchies which are taken to identify project resources.\n     */\n    private static final int PROJECT_PACKAGE_HIERARCHIES = 2;\n    private final RelevantInstructionReducer instructionReducer = new RelevantInstructionReducer();\n    private String projectPackagePrefix;\n\n    /**\n     * Interprets the relevant instructions for the given method.\n     *\n     * @param instructions The instructions to reduce\n     * @return The reduced instructions\n     */\n    List<Instruction> interpretRelevantInstructions(final List<Instruction> instructions) {\n        return instructionReducer.reduceInstructions(instructions);\n    }\n\n    /**\n     * Builds the project package prefix for the class of given method.\n     * The current project which is analyzed is identified by the first two package nodes.\n     */\n    void buildPackagePrefix(final String className) {\n        // TODO test\n        final int lastPackageSeparator = className.lastIndexOf('/');\n        final String packageName = className.substring(0, lastPackageSeparator == -1 ? className.length() : lastPackageSeparator);\n        final String[] splitPackage = packageName.split(\"/\");\n\n        if (splitPackage.length >= PROJECT_PACKAGE_HIERARCHIES) {\n            projectPackagePrefix = IntStream.range(0, PROJECT_PACKAGE_HIERARCHIES).mapToObj(i -> splitPackage[i]).collect(Collectors.joining(\"/\"));\n        } else {\n            projectPackagePrefix = packageName;\n        }\n    }\n\n    /**\n     * Searches for own project method invoke instructions in the given list.\n     *\n     * @param instructions The instructions where to search\n     * @return The found project methods\n     */\n    Set<ProjectMethod> findProjectMethods(final List<Instruction> instructions) {\n        final Set<ProjectMethod> projectMethods = new HashSet<>();\n\n        addProjectMethods(instructions, projectMethods);\n\n        return projectMethods;\n    }\n\n    /**\n     * Adds all project methods called in the given {@code instructions} to the {@code projectMethods} recursively.\n     *\n     * @param instructions   The instructions of the current method\n     * @param projectMethods All found project methods\n     */\n    private void addProjectMethods(final List<Instruction> instructions, final Set<ProjectMethod> projectMethods) {\n        Set<MethodIdentifier> projectMethodIdentifiers = findUnhandledProjectMethodIdentifiers(instructions, projectMethods);\n\n        for (MethodIdentifier identifier : projectMethodIdentifiers) {\n            // TODO cache results -> singleton pool?\n\n            final MethodResult methodResult = visitProjectMethod(identifier);\n            if (methodResult == null) {\n                continue;\n            }\n\n            final List<Instruction> nestedMethodInstructions = interpretRelevantInstructions(methodResult.getInstructions());\n            projectMethods.add(new ProjectMethod(identifier, nestedMethodInstructions));\n            addProjectMethods(nestedMethodInstructions, projectMethods);\n        }\n    }\n\n    private MethodResult visitProjectMethod(MethodIdentifier identifier) {\n        try {\n            final ClassReader classReader = new ContextClassReader(identifier.getContainingClass());\n            final MethodResult methodResult = new MethodResult();\n            methodResult.setOriginalMethodSignature(identifier);\n            final ClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, identifier);\n\n            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n            return methodResult;\n        } catch (IOException e) {\n            LogProvider.error(\"Could not analyze project method \" + identifier.getContainingClass() + \"#\" + identifier.getMethodName());\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n    /**\n     * Returns project method identifiers of invoke instructions which are not included in the {@code projectMethods}.\n     *\n     * @param instructions   The instructions of the current method\n     * @param projectMethods All found project methods\n     * @return The new method identifiers of unhandled project method invoke instructions\n     */\n    private Set<MethodIdentifier> findUnhandledProjectMethodIdentifiers(final List<Instruction> instructions, final Set<ProjectMethod> projectMethods) {\n        // find own methods\n        return instructions.stream().filter(i -> i.getType() == Instruction.InstructionType.INVOKE || i.getType() == Instruction.InstructionType.METHOD_HANDLE)\n                .map(i -> (InvokeInstruction) i).filter(this::isProjectMethod).map(InvokeInstruction::getIdentifier)\n                .filter(i -> projectMethods.stream().noneMatch(m -> m.matches(i)))\n                .collect(Collectors.toSet());\n    }\n\n    /**\n     * Checks if the given instruction invokes a method defined in the analyzed project.\n     *\n     * @param instruction The invoke instruction\n     * @return {@code true} if method was defined in the project\n     */\n    private boolean isProjectMethod(final InvokeInstruction instruction) {\n        final MethodIdentifier identifier = instruction.getIdentifier();\n\n        // check if method is in own package\n        return identifier.getContainingClass().startsWith(projectPackagePrefix);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/ResourceMethodContentAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodPool;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodSimulator;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.Collectors;\n\n/**\n * Analyzes JAX-RS resource methods. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\nclass ResourceMethodContentAnalyzer extends MethodContentAnalyzer {\n\n    private final Lock lock = new ReentrantLock();\n\n    /**\n     * Analyzes the method (including own project methods).\n     *\n     * @param methodResult The method result\n     */\n    void analyze(final MethodResult methodResult) {\n        lock.lock();\n        try {\n            buildPackagePrefix(methodResult.getParentResource().getOriginalClass());\n\n            final List<Instruction> visitedInstructions = interpretRelevantInstructions(methodResult.getInstructions());\n\n            // find project defined methods in invoke occurrences\n            final Set<ProjectMethod> projectMethods = findProjectMethods(visitedInstructions);\n\n            // add project methods to global method pool\n            projectMethods.forEach(MethodPool.getInstance()::addProjectMethod);\n\n            Element returnedElement = new MethodSimulator().simulate(visitedInstructions);\n            final String returnType = methodResult.getOriginalMethodSignature().getReturnType();\n\n            // void resource methods are interpreted later; stop analyzing on error\n            if (Types.PRIMITIVE_VOID.equals(returnType)) {\n                return;\n            }\n\n            if (returnedElement == null) {\n                // happens for abstract methods or if there is no return\n                return;\n            }\n\n            final Set<Object> possibleObjects = returnedElement.getPossibleValues().stream().filter(o -> !(o instanceof HttpResponse))\n                    .collect(Collectors.toSet());\n\n            // for non-Response methods add a default if there are non-Response objects or none objects at all\n            if (!Types.RESPONSE.equals(returnType)) {\n                final HttpResponse defaultResponse = new HttpResponse();\n\n                if (Types.OBJECT.equals(returnType))\n                    defaultResponse.getEntityTypes().addAll(returnedElement.getTypes());\n                else\n                    defaultResponse.getEntityTypes().add(returnType);\n\n                possibleObjects.stream().filter(o -> o instanceof JsonValue).map(o -> (JsonValue) o).forEach(defaultResponse.getInlineEntities()::add);\n\n                defaultResponse.getContentTypes().addAll(methodResult.getResponseMediaTypes());\n\n                methodResult.getResponses().add(defaultResponse);\n            }\n\n            // add Response results as well\n            returnedElement.getPossibleValues().stream().filter(o -> o instanceof HttpResponse).map(o -> (HttpResponse) o).forEach(methodResult.getResponses()::add);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/SubResourceLocatorMethodContentAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.JobRegistry;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodPool;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodSimulator;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport static java.util.Collections.singleton;\n\n/**\n * Analyzes sub-resource-locator methods. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\nclass SubResourceLocatorMethodContentAnalyzer extends MethodContentAnalyzer {\n\n    private final Lock lock = new ReentrantLock();\n    private final MethodSimulator simulator = new MethodSimulator();\n\n    /**\n     * Analyzes the sub-resource locator method as a class result (which will be the content of a method result).\n     *\n     * @param methodResult The method result of the sub-resource locator (containing the instructions, and a sub-resource class result)\n     */\n    void analyze(final MethodResult methodResult) {\n        lock.lock();\n        try {\n            buildPackagePrefix(methodResult.getParentResource().getOriginalClass());\n\n            determineReturnTypes(methodResult).stream()\n                    // FEATURE handle several sub-resource impl's\n                    .reduce((l, r) -> JavaUtils.determineMostSpecificType(l, r))\n                    .ifPresent(t -> registerSubResourceJob(t, methodResult.getSubResource()));\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Determines the possible return types of the sub-resource-locator by analyzing the bytecode.\n     * This will analyze the concrete returned types (which then are further analyzed).\n     */\n    private Set<String> determineReturnTypes(final MethodResult result) {\n        final List<Instruction> visitedInstructions = interpretRelevantInstructions(result.getInstructions());\n\n        // find project defined methods in invoke occurrences\n        final Set<ProjectMethod> projectMethods = findProjectMethods(visitedInstructions);\n\n        // add project methods to global method pool\n        projectMethods.forEach(MethodPool.getInstance()::addProjectMethod);\n\n        final Element returnedElement = simulator.simulate(visitedInstructions);\n        if (returnedElement == null) {\n            // happens for abstract methods or if there is no return\n            return singleton(result.getOriginalMethodSignature().getReturnType());\n        }\n\n        return returnedElement.getTypes();\n    }\n\n    private void registerSubResourceJob(final String type, final ClassResult classResult) {\n        final String className = JavaUtils.toClassName(type);\n        JobRegistry.getInstance().analyzeResourceClass(className, classResult);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/InstructionBuilder.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.Opcodes;\n\nimport java.lang.reflect.Field;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.of;\nimport static org.objectweb.asm.Opcodes.*;\nimport static org.objectweb.asm.util.Printer.OPCODES;\n\n/**\n * @author Sebastian Daschner\n */\npublic final class InstructionBuilder {\n\n    private InstructionBuilder() {\n        throw new UnsupportedOperationException();\n    }\n\n    public static Instruction buildFieldInstruction(final int opcode, final String ownerClass, final String name, final String desc, final Label label) {\n        // TODO remove\n        if (org.objectweb.asm.Type.getObjectType(ownerClass).getClassName().equals(ownerClass.replace('.', '/')))\n            throw new AssertionError(\"!\");\n\n        final String opcodeName = OPCODES[opcode];\n\n        switch (opcode) {\n            case GETSTATIC:\n                final Object value = getStaticValue(name, ownerClass);\n                return new GetStaticInstruction(ownerClass, name, desc, value, label);\n            case PUTSTATIC:\n                return new SizeChangingInstruction(opcodeName, 0, 1, label);\n            case GETFIELD:\n                return new GetFieldInstruction(ownerClass, name, desc, label);\n            case PUTFIELD:\n                return new SizeChangingInstruction(opcodeName, 0, 2, label);\n            default:\n                throw new IllegalArgumentException(\"Opcode \" + opcode + \" not a field instruction\");\n        }\n    }\n\n    public static Instruction buildInstruction(final int opcode, final Label label) {\n        final String opcodeName = OPCODES[opcode];\n\n        switch (opcode) {\n            case ICONST_0:\n                return new PushInstruction(0, PRIMITIVE_INT, label);\n            case ICONST_1:\n                return new PushInstruction(1, PRIMITIVE_INT, label);\n            case ICONST_2:\n                return new PushInstruction(2, PRIMITIVE_INT, label);\n            case ICONST_3:\n                return new PushInstruction(3, PRIMITIVE_INT, label);\n            case ICONST_4:\n                return new PushInstruction(4, PRIMITIVE_INT, label);\n            case ICONST_5:\n                return new PushInstruction(5, PRIMITIVE_INT, label);\n            case ICONST_M1:\n                return new PushInstruction(-1, PRIMITIVE_INT, label);\n            case DCONST_0:\n                return new PushInstruction(0d, PRIMITIVE_DOUBLE, label);\n            case DCONST_1:\n                return new PushInstruction(1d, PRIMITIVE_DOUBLE, label);\n            case FCONST_0:\n                return new PushInstruction(1f, PRIMITIVE_FLOAT, label);\n            case FCONST_1:\n                return new PushInstruction(1f, PRIMITIVE_FLOAT, label);\n            case FCONST_2:\n                return new PushInstruction(2f, PRIMITIVE_FLOAT, label);\n            case LCONST_0:\n                return new PushInstruction(0L, PRIMITIVE_LONG, label);\n            case LCONST_1:\n                return new PushInstruction(1L, PRIMITIVE_LONG, label);\n            case IALOAD:\n            case LALOAD:\n            case FALOAD:\n            case DALOAD:\n            case AALOAD:\n            case BALOAD:\n            case CALOAD:\n            case SALOAD:\n                return new SizeChangingInstruction(opcodeName, 1, 2, label);\n            case IASTORE:\n            case LASTORE:\n            case FASTORE:\n            case DASTORE:\n            case AASTORE:\n            case BASTORE:\n            case CASTORE:\n            case SASTORE:\n                return new SizeChangingInstruction(opcodeName, 0, 3, label);\n            case DUP_X1:\n            case DUP2_X1:\n                return new SizeChangingInstruction(opcodeName, 3, 2, label);\n            case DUP_X2:\n            case DUP2_X2:\n                return new SizeChangingInstruction(opcodeName, 4, 3, label);\n            case ARRAYLENGTH:\n            case I2L:\n            case I2F:\n            case I2D:\n            case L2I:\n            case L2F:\n            case L2D:\n            case F2I:\n            case F2L:\n            case F2D:\n            case D2I:\n            case D2L:\n            case D2F:\n            case I2B:\n            case I2C:\n            case I2S:\n            case INEG:\n            case LNEG:\n            case FNEG:\n            case DNEG:\n            case SWAP:\n                return new SizeChangingInstruction(opcodeName, 1, 1, label);\n            case IADD:\n            case LADD:\n            case FADD:\n            case DADD:\n            case ISUB:\n            case LSUB:\n            case FSUB:\n            case DSUB:\n            case IMUL:\n            case LMUL:\n            case FMUL:\n            case DMUL:\n            case IDIV:\n            case LDIV:\n            case FDIV:\n            case DDIV:\n            case IREM:\n            case LREM:\n            case FREM:\n            case DREM:\n            case ISHL:\n            case LSHL:\n            case ISHR:\n            case LSHR:\n            case IUSHR:\n            case LUSHR:\n            case IAND:\n            case LAND:\n            case IOR:\n            case LOR:\n            case IXOR:\n            case LXOR:\n            case LCMP:\n            case FCMPL:\n            case FCMPG:\n            case DCMPL:\n            case DCMPG:\n                return new SizeChangingInstruction(opcodeName, 1, 2, label);\n            case IRETURN:\n            case LRETURN:\n            case FRETURN:\n            case DRETURN:\n            case ARETURN:\n                return new ReturnInstruction(label);\n            case ATHROW:\n                return new ThrowInstruction(label);\n            case RETURN:\n            case NOP:\n                return new DefaultInstruction(opcodeName, label);\n            case POP:\n            case POP2:\n            case MONITORENTER:\n            case MONITOREXIT:\n                return new SizeChangingInstruction(opcodeName, 0, 1, label);\n            case ACONST_NULL:\n                return new SizeChangingInstruction(opcodeName, 1, 0, label);\n            case DUP:\n            case DUP2:\n                return new DupInstruction(label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    public static Instruction buildLoadStoreInstruction(int opcode, int index, Label label) {\n        switch (opcode) {\n            case ILOAD:\n            case LLOAD:\n            case FLOAD:\n            case DLOAD:\n            case ALOAD:\n                return new LoadStoreInstructionPlaceholder(Instruction.InstructionType.LOAD_PLACEHOLDER, index, label);\n            case ISTORE:\n            case LSTORE:\n            case FSTORE:\n            case DSTORE:\n            case ASTORE:\n                return new LoadStoreInstructionPlaceholder(Instruction.InstructionType.STORE_PLACEHOLDER, index, label);\n            case RET:\n                return new DefaultInstruction(OPCODES[opcode], label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    public static Instruction buildTypeInstruction(int opcode, String className, final Label label) {\n        final String opcodeName = OPCODES[opcode];\n\n        switch (opcode) {\n            case NEW:\n                return new NewInstruction(className, label);\n            case ANEWARRAY:\n            case INSTANCEOF:\n                return new SizeChangingInstruction(opcodeName, 1, 1, label);\n            case CHECKCAST:\n                return new DefaultInstruction(opcodeName, label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    public static InvokeInstruction buildInvokeInstruction(final int opcode, String containingClass, String name, String desc, final Label label) {\n        switch (opcode) {\n            case INVOKEINTERFACE:\n            case INVOKEVIRTUAL:\n            case INVOKESPECIAL:\n                return new InvokeInstruction(of(containingClass, name, desc, false), label);\n            case INVOKESTATIC:\n                return new InvokeInstruction(of(containingClass, name, desc, true), label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    public static Instruction buildInvokeDynamic(final String className, final String name, final String desc, final Handle handle, final Label label) {\n        final MethodIdentifier actualIdentifier = of(handle.getOwner(), handle.getName(), handle.getDesc(), handle.getTag() == Opcodes.H_INVOKESTATIC);\n\n        final MethodIdentifier dynamicIdentifier = of(className, name, desc, true);\n        return new InvokeDynamicInstruction(actualIdentifier, dynamicIdentifier, label);\n    }\n\n    public static Instruction buildJumpInstruction(int opcode, final Label label) {\n        final String opcodeName = OPCODES[opcode];\n\n        switch (opcode) {\n            case IFEQ:\n            case IFNE:\n            case IFLT:\n            case IFGE:\n            case IFGT:\n            case IFLE:\n            case IFNULL:\n            case IFNONNULL:\n                return new SizeChangingInstruction(opcodeName, 0, 1, label);\n            case JSR:\n                return new SizeChangingInstruction(opcodeName, 1, 0, label);\n            case GOTO:\n                return new DefaultInstruction(opcodeName, label);\n            case IF_ICMPEQ:\n            case IF_ICMPNE:\n            case IF_ICMPLT:\n            case IF_ICMPGE:\n            case IF_ICMPGT:\n            case IF_ICMPLE:\n            case IF_ACMPEQ:\n            case IF_ACMPNE:\n                return new SizeChangingInstruction(opcodeName, 0, 2, label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    public static Instruction buildIntInstruction(int opcode, int operand, final Label label) {\n        switch (opcode) {\n            case BIPUSH:\n            case SIPUSH:\n                return new PushInstruction(operand, PRIMITIVE_INT, label);\n            case NEWARRAY:\n                return new SizeChangingInstruction(OPCODES[NEWARRAY], 1, 1, label);\n            default:\n                throw new IllegalArgumentException(\"Unexpected opcode \" + opcode);\n        }\n    }\n\n    private static Object getStaticValue(String name, String containingClass) {\n        final Field field;\n        try {\n            // needs to load same class instance in Maven plugin, not from extended classloader\n            final Class<?> clazz = Class.forName(containingClass.replace('/', '.'));\n            field = clazz.getDeclaredField(name);\n            field.setAccessible(true);\n            return field.get(null);\n        } catch (Exception e) {\n            LogProvider.error(\"Could not access static property, reason: \" + e.getMessage());\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/InstructionFinder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.LoadInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.LoadStoreInstruction;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.function.Predicate;\n\n/**\n * Searches for specific instruction occurrences in the byte code.\n *\n * @author Sebastian Daschner\n */\nfinal class InstructionFinder {\n\n    private InstructionFinder() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Searches for all LOAD indexes which occur in the given instructions.\n     * The LOAD instruction is checked against the given predicate if it should be ignored.\n     *\n     * @param instructions  The instructions where to search\n     * @param isLoadIgnored The ignore predicate\n     * @return All found LOAD indexes\n     */\n    static Set<Integer> findLoadIndexes(final List<Instruction> instructions, final Predicate<LoadInstruction> isLoadIgnored) {\n        return instructions.stream().filter(i -> i.getType() == Instruction.InstructionType.LOAD).map(i -> (LoadInstruction) i)\n                .filter(i -> !isLoadIgnored.test(i)).map(LoadInstruction::getNumber).collect(TreeSet::new, Set::add, Set::addAll);\n    }\n\n    /**\n     * Searches for all LOAD &amp; STORE occurrences with {@code index} in the given instructions.\n     *\n     * @param index        The LOAD / STORE index\n     * @param instructions The instructions where to search\n     * @return The positions of all found LOAD_{@code index} / STORE_{@code index}\n     */\n    static Set<Integer> findLoadStores(final int index, final List<Instruction> instructions) {\n        final Predicate<Instruction> loadStoreType = instruction -> instruction.getType() == Instruction.InstructionType.LOAD\n                || instruction.getType() == Instruction.InstructionType.STORE;\n        return find(loadStoreType.and(instruction -> ((LoadStoreInstruction) instruction).getNumber() == index), instructions);\n    }\n\n    /**\n     * Searches for return instructions in the given instructions.\n     *\n     * @param instructions The instructions where to search\n     * @return The positions of all found return instructions\n     */\n    static Set<Integer> findReturnsAndThrows(final List<Instruction> instructions) {\n        return find(instruction -> instruction.getType() == Instruction.InstructionType.RETURN || instruction.getType() == Instruction.InstructionType.THROW, instructions);\n    }\n\n    /**\n     * Searches for certain instruction positions be testing against the predicate.\n     *\n     * @param predicate    The criteria predicate\n     * @param instructions The instructions where to search\n     * @return The positions of all matching instructions\n     */\n    private static Set<Integer> find(final Predicate<Instruction> predicate, final List<Instruction> instructions) {\n        final Set<Integer> positions = new HashSet<>();\n\n        for (int i = 0; i < instructions.size(); i++) {\n            final Instruction instruction = instructions.get(i);\n            if (predicate.test(instruction)) {\n                positions.add(i);\n            }\n        }\n\n        return positions;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/RelevantInstructionReducer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.LoadInstruction;\n\nimport java.util.*;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/**\n * Determines the instructions, which are relevant for the return value of a method by simulating a runtime stack with the byte code. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\npublic class RelevantInstructionReducer {\n\n    /**\n     * These variable names will not be backtracked.\n     */\n    private static final String[] VARIABLE_NAMES_TO_IGNORE = {\"this\"};\n    private final Lock lock = new ReentrantLock();\n    private final StackSizeSimulator stackSizeSimulator = new StackSizeSimulator();\n    private List<Instruction> instructions;\n\n    /**\n     * Returns all instructions which are somewhat \"relevant\" for the returned object of the method.\n     * The instructions are visited backwards - starting from the return statement.\n     * Load and Store operations are handled as well.\n     *\n     * @param instructions The instructions to reduce\n     * @return The relevant instructions\n     */\n    public List<Instruction> reduceInstructions(final List<Instruction> instructions) {\n        lock.lock();\n        try {\n            this.instructions = instructions;\n            stackSizeSimulator.buildStackSizes(instructions);\n\n            return reduceInstructionsInternal(instructions);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Returns all reduced instructions.\n     *\n     * @param instructions All instructions\n     * @return The relevant instructions\n     */\n    private List<Instruction> reduceInstructionsInternal(final List<Instruction> instructions) {\n        final List<Instruction> visitedInstructions = new LinkedList<>();\n        final Set<Integer> visitedInstructionPositions = new HashSet<>();\n        final Set<Integer> handledLoadIndexes = new HashSet<>();\n        final Set<Integer> backtrackPositions = new LinkedHashSet<>(findSortedBacktrackPositions());\n\n        while (!visitedInstructionPositions.containsAll(backtrackPositions)) {\n\n            // unvisited backtrack position\n            final int backtrackPosition = backtrackPositions.stream().filter(pos -> !visitedInstructionPositions.contains(pos))\n                    .findFirst().orElseThrow(IllegalStateException::new);\n\n            final List<Integer> lastVisitedPositions = stackSizeSimulator.simulateStatementBackwards(backtrackPosition);\n            final List<Instruction> lastVisitedInstructions = lastVisitedPositions.stream().map(instructions::get).collect(Collectors.toList());\n\n            visitedInstructionPositions.addAll(lastVisitedPositions);\n            visitedInstructions.addAll(lastVisitedInstructions);\n\n            // unhandled load indexes\n            final Set<Integer> unhandledLoadIndexes = findUnhandledLoadIndexes(handledLoadIndexes, lastVisitedInstructions);\n\n            // for each load occurrence index -> find load/store backtrack positions (reverse order matters here)\n            final SortedSet<Integer> loadStoreBacktrackPositions = findLoadStoreBacktrackPositions(unhandledLoadIndexes);\n\n            handledLoadIndexes.addAll(unhandledLoadIndexes);\n\n            loadStoreBacktrackPositions.stream().forEach(backtrackPositions::add);\n        }\n\n        // sort in method natural order\n        Collections.reverse(visitedInstructions);\n\n        return visitedInstructions;\n    }\n\n    private List<Integer> findSortedBacktrackPositions() {\n        final List<Integer> startPositions = new LinkedList<>(InstructionFinder.findReturnsAndThrows(instructions));\n\n        // start with last return\n        Collections.sort(startPositions, Comparator.reverseOrder());\n        return startPositions;\n    }\n\n\n    /**\n     * Searches for load indexes in the {@code lastVisitedInstructions} which are not contained in {@code handledLoadIndexes}.\n     *\n     * @param handledLoadIndexes      The load indexed which have been handled so far\n     * @param lastVisitedInstructions The last visited instructions\n     * @return The unhandled load indexes\n     */\n    private Set<Integer> findUnhandledLoadIndexes(final Set<Integer> handledLoadIndexes, final List<Instruction> lastVisitedInstructions) {\n        final Set<Integer> lastLoadIndexes = InstructionFinder.findLoadIndexes(lastVisitedInstructions, RelevantInstructionReducer::isLoadIgnored);\n\n        return lastLoadIndexes.stream().filter(k -> !handledLoadIndexes.contains(k)).collect(Collectors.toSet());\n    }\n\n    /**\n     * Checks if the given LOAD instruction should be ignored for backtracking.\n     *\n     * @param instruction The instruction to check\n     * @return {@code true} if the LOAD instruction will be ignored\n     */\n    private static boolean isLoadIgnored(final LoadInstruction instruction) {\n        return Stream.of(VARIABLE_NAMES_TO_IGNORE).anyMatch(instruction.getName()::equals);\n    }\n\n    /**\n     * Returns all backtrack positions of the given LOAD / STORE indexes in the instructions.\n     * The backtrack positions of both LOAD and store instructions are the next positions where the runtime stack size is {@code 0}.\n     *\n     * @param unhandledLoadIndexes The LOAD/STORE indexes to find\n     * @return The backtrack positions of the LOAD / STORE indexes\n     */\n    private SortedSet<Integer> findLoadStoreBacktrackPositions(final Set<Integer> unhandledLoadIndexes) {\n        return unhandledLoadIndexes.stream()\n                .map(index -> stackSizeSimulator.findLoadStoreBacktrackPositions(InstructionFinder.findLoadStores(index, instructions)))\n                .collect(() -> new TreeSet<>(Comparator.reverseOrder()), Set::addAll, Set::addAll);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/StackSizeSimulator.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction;\n\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/**\n * Simulates runtime stack sizes of instructions.\n *\n * @author Sebastian Daschner\n */\nclass StackSizeSimulator {\n\n    private List<Pair<Integer, Integer>> stackSizes;\n\n    /**\n     * Initializes the runtime stack sizes with the given instructions. This has to be called before {@link StackSizeSimulator#simulateStatementBackwards}\n     *\n     * @param instructions The instructions to simulate\n     */\n    void buildStackSizes(final List<Instruction> instructions) {\n        stackSizes = new ArrayList<>();\n        int stackSize = 0;\n\n        for (Instruction instruction : instructions) {\n            final int previousStackSize = stackSize;\n\n            stackSize += instruction.getStackSizeDifference();\n\n            if (isStackCleared(instruction))\n                stackSize = 0;\n\n            if (stackSize < 0) {\n                throw new IllegalStateException(\"Runtime stack under-flow occurred.\");\n            }\n\n            stackSizes.add(Pair.of(previousStackSize, stackSize));\n        }\n    }\n\n    /**\n     * Checks if the stack will be cleared on invoking the given instruction.\n     *\n     * @param instruction The instruction\n     * @return {@code true} if the stack will be cleared\n     */\n    private static boolean isStackCleared(final Instruction instruction) {\n        return instruction.getType() == Instruction.InstructionType.RETURN || instruction.getType() == Instruction.InstructionType.THROW;\n    }\n\n    /**\n     * Returns the instruction positions which are visited <i>backwards</i> from {@code backtrackPosition}\n     * until the runtime stack is empty.\n     *\n     * @param backtrackPosition The backtrack position where to start\n     * @return All positions <i>backwards</i> until the previous empty position\n     */\n    List<Integer> simulateStatementBackwards(final int backtrackPosition) {\n        // search for previous zero-position in stackSizes\n        int currentPosition = backtrackPosition;\n\n        // check against stack size before the instruction was executed\n        while (stackSizes.get(currentPosition).getLeft() > 0) {\n            currentPosition--;\n        }\n\n        return Stream.iterate(backtrackPosition, c -> --c).limit(backtrackPosition - currentPosition + 1)\n                .collect(LinkedList::new, Collection::add, Collection::addAll);\n    }\n\n    /**\n     * Returns all backtrack positions of the given instruction positions.\n     * The backtrack positions of both LOAD and store instructions are the next positions where the runtime stack size is {@code 0}.\n     *\n     * @param loadStorePositions The LOAD/STORE positions\n     * @return The backtrack positions\n     */\n    Set<Integer> findLoadStoreBacktrackPositions(final Set<Integer> loadStorePositions) {\n        // go to this or next zero-position\n        return loadStorePositions.stream().map(this::findBacktrackPosition).collect(Collectors.toSet());\n    }\n\n    /**\n     * Returns the next position where the stack will be empty.\n     *\n     * @param position The current position\n     * @return The next empty position\n     */\n    private int findBacktrackPosition(final int position) {\n        int currentPosition = position;\n\n        // check against stack size after the instruction was executed\n        while (stackSizes.get(currentPosition).getRight() > 0) {\n            currentPosition++;\n        }\n\n        return currentPosition;\n    }\n\n}"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/simulation/InjectableArgumentMethodSimulator.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.IntStream;\n\n/**\n * Simulates the the instructions of a project method. The parameters of the method can be set with the actual arguments. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\npublic class InjectableArgumentMethodSimulator extends MethodSimulator {\n\n    /**\n     * The called methods in a single recursive method simulation. Used to prevent infinite loops while analysing recursion.\n     */\n    private static final List<MethodIdentifier> EXECUTED_PATH_METHODS = Collections.synchronizedList(new LinkedList<>());\n\n    private final Lock lock = new ReentrantLock();\n\n    /**\n     * Simulates the instructions of the method which will be called with the given arguments.\n     *\n     * @param arguments    The argument values\n     * @param instructions The instructions of the method\n     * @param identifier   The identifier of the method\n     * @return The return value or {@code null} if return type is void\n     */\n    public Element simulate(final List<Element> arguments, final List<Instruction> instructions, final MethodIdentifier identifier) {\n        // prevent infinite loops on analysing recursion\n        if (EXECUTED_PATH_METHODS.contains(identifier))\n            return new Element();\n\n        lock.lock();\n        EXECUTED_PATH_METHODS.add(identifier);\n        try {\n\n            injectArguments(arguments, identifier);\n\n            return simulateInternal(instructions);\n        } finally {\n            EXECUTED_PATH_METHODS.remove(identifier);\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Injects the arguments of the method invocation to the local variables.\n     *\n     * @param arguments The argument values\n     */\n    private void injectArguments(final List<Element> arguments, final MethodIdentifier identifier) {\n        final boolean staticMethod = identifier.isStaticMethod();\n        final int startIndex = staticMethod ? 0 : 1;\n        final int endIndex = staticMethod ? arguments.size() - 1 : arguments.size();\n\n        IntStream.rangeClosed(startIndex, endIndex).forEach(i -> localVariables.put(i, arguments.get(staticMethod ? i : i - 1)));\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/simulation/KnownJsonResultMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.IdentifiableMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport java.util.List;\nimport java.util.function.BiFunction;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\n/**\n * Known JSON methods which apply logic to the result or to the return element.\n *\n * @author Sebastian Daschner\n */\nenum KnownJsonResultMethod implements IdentifiableMethod {\n\n    JSON_ARRAY_BUILDER_CREATE(MethodIdentifier.ofStatic(CLASS_JSON, \"createArrayBuilder\", JSON_ARRAY_BUILDER), (object, arguments) -> new Element(JSON_ARRAY, new JsonArray())),\n\n    JSON_ARRAY_BUILDER_ADD_BIG_DECIMAL(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, BIG_DECIMAL),\n            (object, arguments) -> addToArray(object, arguments, BIG_DECIMAL)),\n\n    JSON_ARRAY_BUILDER_ADD_BIG_INTEGER(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, BIG_INTEGER),\n            (object, arguments) -> addToArray(object, arguments, BIG_INTEGER)),\n\n    JSON_ARRAY_BUILDER_ADD_STRING(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, STRING),\n            (object, arguments) -> addToArray(object, arguments, STRING)),\n\n    JSON_ARRAY_BUILDER_ADD_INT(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, PRIMITIVE_INT),\n            (object, arguments) -> addToArray(object, arguments, INTEGER)),\n\n    JSON_ARRAY_BUILDER_ADD_LONG(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, PRIMITIVE_LONG),\n            (object, arguments) -> addToArray(object, arguments, LONG)),\n\n    JSON_ARRAY_BUILDER_ADD_DOUBLE(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, PRIMITIVE_DOUBLE),\n            (object, arguments) -> addToArray(object, arguments, DOUBLE)),\n\n    JSON_ARRAY_BUILDER_ADD_BOOLEAN(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, PRIMITIVE_BOOLEAN),\n            (object, arguments) -> addToArray(object, arguments, PRIMITIVE_BOOLEAN)),\n\n    JSON_ARRAY_BUILDER_ADD_JSON(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, JSON_VALUE),\n            KnownJsonResultMethod::addToArray),\n\n    JSON_ARRAY_BUILDER_ADD_JSON_OBJECT(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, JSON_OBJECT_BUILDER), (object, arguments) ->\n            addToArray(object, arguments, JSON_OBJECT)),\n\n    JSON_ARRAY_BUILDER_ADD_JSON_ARRAY(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"add\", JSON_ARRAY_BUILDER, JSON_ARRAY_BUILDER), (object, arguments) ->\n            addToArray(object, arguments, JSON_ARRAY)),\n\n    JSON_ARRAY_BUILDER_ADD_NULL(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"addNull\", JSON_ARRAY_BUILDER),\n            (object, arguments) -> {\n                object.getPossibleValues().stream().filter(o -> o instanceof JsonArray).map(o -> (JsonArray) o)\n                        .forEach(a -> a.getElements().add(new Element(OBJECT, null)));\n                return object;\n            }),\n\n    JSON_ARRAY_BUILDER_BUILD(MethodIdentifier.ofNonStatic(CLASS_JSON_ARRAY_BUILDER, \"build\", JSON_ARRAY), (object, arguments) -> {\n        Element json = new Element(JSON_ARRAY);\n        json.getPossibleValues().addAll(object.getPossibleValues());\n        return json;\n    }),\n\n    JSON_OBJECT_BUILDER_CREATE(MethodIdentifier.ofStatic(CLASS_JSON, \"createObjectBuilder\", JSON_OBJECT_BUILDER), (object, arguments) -> new Element(JSON_OBJECT, new JsonObject())),\n\n    JSON_OBJECT_BUILDER_ADD_BIG_DECIMAL(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, BIG_DECIMAL),\n            (object, arguments) -> mergeJsonStructure(object, arguments, BIG_DECIMAL)),\n\n    JSON_OBJECT_BUILDER_ADD_BIG_INTEGER(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, BIG_INTEGER),\n            (object, arguments) -> mergeJsonStructure(object, arguments, BIG_INTEGER)),\n\n    JSON_OBJECT_BUILDER_ADD_STRING(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, STRING),\n            (object, arguments) -> mergeJsonStructure(object, arguments, STRING)),\n\n    JSON_OBJECT_BUILDER_ADD_INT(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, PRIMITIVE_INT),\n            (object, arguments) -> mergeJsonStructure(object, arguments, INTEGER)),\n\n    JSON_OBJECT_BUILDER_ADD_LONG(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, PRIMITIVE_LONG),\n            (object, arguments) -> mergeJsonStructure(object, arguments, LONG)),\n\n    JSON_OBJECT_BUILDER_ADD_DOUBLE(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, PRIMITIVE_DOUBLE),\n            (object, arguments) -> mergeJsonStructure(object, arguments, DOUBLE)),\n\n    JSON_OBJECT_BUILDER_ADD_BOOLEAN(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, PRIMITIVE_BOOLEAN),\n            (object, arguments) -> mergeJsonStructure(object, arguments, PRIMITIVE_BOOLEAN)),\n\n    JSON_OBJECT_BUILDER_ADD_JSON(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, JSON_VALUE),\n            KnownJsonResultMethod::mergeJsonStructure),\n\n    JSON_OBJECT_BUILDER_ADD_JSON_OBJECT(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, JSON_OBJECT_BUILDER), (object, arguments) ->\n            mergeJsonStructure(object, arguments, JSON_OBJECT)),\n\n    JSON_OBJECT_BUILDER_ADD_JSON_ARRAY(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"add\", JSON_OBJECT_BUILDER, STRING, JSON_ARRAY_BUILDER), (object, arguments) ->\n            mergeJsonStructure(object, arguments, JSON_ARRAY)),\n\n    JSON_OBJECT_BUILDER_ADD_NULL(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"addNull\", JSON_OBJECT_BUILDER, STRING),\n            (object, arguments) -> {\n                object.getPossibleValues().stream()\n                        .filter(o -> o instanceof JsonObject).map(o -> (JsonObject) o)\n                        .forEach(o -> arguments.get(0).getPossibleValues().stream().map(s -> (String) s)\n                                .forEach(s -> o.getStructure().merge(s, new Element(OBJECT, null), Element::merge)));\n                return object;\n            }),\n\n    JSON_OBJECT_BUILDER_BUILD(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT_BUILDER, \"build\", JSON_OBJECT), (object, arguments) -> {\n        final Element json = new Element(JSON_OBJECT);\n        json.getPossibleValues().addAll(object.getPossibleValues());\n        return json;\n    }),\n\n    JSON_OBJECT_GET_BOOLEAN(MethodIdentifier.ofNonStatic(CLASS_JSON_OBJECT, \"getBoolean\", PRIMITIVE_BOOLEAN, STRING),\n            (object, arguments) -> object.getPossibleValues().stream()\n                    .filter(o -> o instanceof JsonObject).map(o -> (JsonObject) o)\n                    .map(o -> arguments.get(0).getPossibleValues().stream()\n                            .map(s -> (String) s).map(s -> o.getStructure().get(s))\n                            .reduce(new Element(PRIMITIVE_BOOLEAN), Element::merge))\n                    .reduce(new Element(PRIMITIVE_BOOLEAN), Element::merge));\n\n    private final MethodIdentifier identifier;\n\n    private final BiFunction<Element, List<Element>, Element> function;\n\n    KnownJsonResultMethod(final MethodIdentifier identifier,\n                          final BiFunction<Element, List<Element>, Element> function) {\n        this.identifier = identifier;\n        this.function = function;\n    }\n\n    @Override\n    public Element invoke(final Element object, final List<Element> arguments) {\n        if (arguments.size() != identifier.getParameters().size())\n            throw new IllegalArgumentException(\"Method arguments do not match expected signature!\");\n\n        return function.apply(object, arguments);\n    }\n\n    @Override\n    public boolean matches(final MethodIdentifier identifier) {\n        return this.identifier.equals(identifier);\n    }\n\n    private static Element addToArray(final Element object, final List<Element> arguments) {\n        return addToArray(object, arguments.get(0));\n    }\n\n    private static Element addToArray(final Element object, final List<Element> arguments, final String typeOverride) {\n        final Element element = new Element(typeOverride);\n        element.getPossibleValues().addAll(arguments.get(0).getPossibleValues());\n        return addToArray(object, element);\n    }\n\n    private static Element addToArray(final Element object, final Element argument) {\n        object.getPossibleValues().stream()\n                .filter(o -> o instanceof JsonArray).map(o -> (JsonArray) o)\n                .forEach(a -> a.getElements().add(argument));\n        return object;\n    }\n\n    private static Element mergeJsonStructure(final Element object, final List<Element> arguments) {\n        final Element element = new Element(arguments.get(1).getTypes());\n        element.merge(arguments.get(1));\n        return mergeJsonStructure(object, arguments.get(0), element);\n    }\n\n    private static Element mergeJsonStructure(final Element object, final List<Element> arguments, final String typeOverride) {\n        final Element element = new Element(typeOverride);\n        element.getPossibleValues().addAll(arguments.get(1).getPossibleValues());\n        return mergeJsonStructure(object, arguments.get(0), element);\n    }\n\n    private static Element mergeJsonStructure(final Element object, final Element key, final Element argument) {\n        object.getPossibleValues().stream()\n                .filter(o -> o instanceof JsonObject).map(o -> (JsonObject) o)\n                .forEach(o -> key.getPossibleValues().stream().map(s -> (String) s)\n                        .forEach(s -> o.getStructure().merge(s, argument, Element::merge)));\n        return object;\n    }\n\n}\n\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/simulation/KnownResponseResultMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.MethodHandle;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.IdentifiableMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.Method;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport javax.ws.rs.core.HttpHeaders;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.function.BiFunction;\nimport java.util.stream.Collectors;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.INITIALIZER_NAME;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.ofNonStatic;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.ofStatic;\n\n/**\n * Known methods which apply logic to the result or to the return element.\n *\n * @author Sebastian Daschner\n */\nenum KnownResponseResultMethod implements IdentifiableMethod {\n\n    // non-static methods in ResponseBuilder --------------------------\n\n    RESPONSE_BUILDER_BUILD(ofNonStatic(CLASS_RESPONSE_BUILDER, \"build\", RESPONSE), (object, arguments) -> object),\n\n    RESPONSE_BUILDER_CACHE_CONTROL(ofNonStatic(CLASS_RESPONSE_BUILDER, \"cacheControl\", RESPONSE_BUILDER, \"Ljavax/ws/rs/core/CacheControl;\"), (object, arguments) ->\n            addHeader(object, HttpHeaders.CACHE_CONTROL)),\n\n    RESPONSE_BUILDER_CONTENT_LOCATION(ofNonStatic(CLASS_RESPONSE_BUILDER, \"contentLocation\", RESPONSE_BUILDER, URI), (object, arguments) ->\n            addHeader(object, HttpHeaders.CONTENT_LOCATION)),\n\n    RESPONSE_BUILDER_COOKIE(ofNonStatic(CLASS_RESPONSE_BUILDER, \"cookie\", RESPONSE_BUILDER, \"[Ljavax/ws/rs/core/NewCookie;\"), (object, arguments) ->\n            addHeader(object, HttpHeaders.SET_COOKIE)),\n\n    RESPONSE_BUILDER_ENCODING(ofNonStatic(CLASS_RESPONSE_BUILDER, \"encoding\", RESPONSE_BUILDER, STRING), (object, arguments) ->\n            addHeader(object, HttpHeaders.CONTENT_ENCODING)),\n\n    RESPONSE_BUILDER_ENTITY(ofNonStatic(CLASS_RESPONSE_BUILDER, \"entity\", RESPONSE_BUILDER, OBJECT), (object, arguments) ->\n            addEntity(object, arguments.get(0))),\n\n    RESPONSE_BUILDER_ENTITY_ANNOTATION(ofNonStatic(CLASS_RESPONSE_BUILDER, \"entity\", RESPONSE_BUILDER, OBJECT, \"[Ljava/lang/annotation/Annotation;\"), (object, arguments) ->\n            addEntity(object, arguments.get(0))),\n\n    RESPONSE_BUILDER_EXPIRES(ofNonStatic(CLASS_RESPONSE_BUILDER, \"expires\", RESPONSE_BUILDER, DATE), (object, arguments) ->\n            addHeader(object, HttpHeaders.EXPIRES)),\n\n    RESPONSE_BUILDER_HEADER(ofNonStatic(CLASS_RESPONSE_BUILDER, \"header\", RESPONSE_BUILDER, STRING, OBJECT), (object, arguments) -> {\n        arguments.get(0).getPossibleValues().stream()\n                .map(header -> (String) header).forEach(h -> addHeader(object, h));\n        return object;\n    }),\n\n    RESPONSE_BUILDER_LANGUAGE_LOCALE(ofNonStatic(CLASS_RESPONSE_BUILDER, \"language\", RESPONSE_BUILDER, \"Ljava/util/Locale;\"), (object, arguments) ->\n            addHeader(object, HttpHeaders.CONTENT_LANGUAGE)),\n\n    RESPONSE_BUILDER_LANGUAGE_STRING(ofNonStatic(CLASS_RESPONSE_BUILDER, \"language\", RESPONSE_BUILDER, STRING), (object, arguments) ->\n            addHeader(object, HttpHeaders.CONTENT_LANGUAGE)),\n\n    RESPONSE_BUILDER_LAST_MODIFIED(ofNonStatic(CLASS_RESPONSE_BUILDER, \"lastModified\", RESPONSE_BUILDER, DATE), (object, arguments) ->\n            addHeader(object, HttpHeaders.LAST_MODIFIED)),\n\n    RESPONSE_BUILDER_LINK_URI(ofNonStatic(CLASS_RESPONSE_BUILDER, \"link\", RESPONSE_BUILDER, URI, STRING), (object, arguments) ->\n            addHeader(object, HttpHeaders.LINK)),\n\n    RESPONSE_BUILDER_LINK_STRING(ofNonStatic(CLASS_RESPONSE_BUILDER, \"link\", RESPONSE_BUILDER, STRING, STRING), (object, arguments) ->\n            addHeader(object, HttpHeaders.LINK)),\n\n    RESPONSE_BUILDER_LINKS(ofNonStatic(CLASS_RESPONSE_BUILDER, \"links\", RESPONSE_BUILDER, \"[Ljavax/ws/rs/core/Link;\"), (object, arguments) ->\n            addHeader(object, HttpHeaders.LINK)),\n\n    RESPONSE_BUILDER_LOCATION(ofNonStatic(CLASS_RESPONSE_BUILDER, \"location\", RESPONSE_BUILDER, URI), (object, arguments) ->\n            addHeader(object, HttpHeaders.LOCATION)),\n\n    RESPONSE_BUILDER_STATUS_ENUM(ofNonStatic(CLASS_RESPONSE_BUILDER, \"status\", RESPONSE_BUILDER, RESPONSE_STATUS), (object, arguments) -> {\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    RESPONSE_BUILDER_STATUS_INT(ofNonStatic(CLASS_RESPONSE_BUILDER, \"status\", RESPONSE_BUILDER, PRIMITIVE_INT), (object, arguments) -> {\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    RESPONSE_BUILDER_TAG_ENTITY(ofNonStatic(CLASS_RESPONSE_BUILDER, \"tag\", RESPONSE_BUILDER, ENTITY_TAG), (object, arguments) ->\n            addHeader(object, HttpHeaders.ETAG)),\n\n    RESPONSE_BUILDER_TAG_STRING(ofNonStatic(CLASS_RESPONSE_BUILDER, \"tag\", RESPONSE_BUILDER, STRING), (object, arguments) ->\n            addHeader(object, HttpHeaders.ETAG)),\n\n    RESPONSE_BUILDER_TYPE(ofNonStatic(CLASS_RESPONSE_BUILDER, \"type\", RESPONSE_BUILDER, \"Ljavax/ws/rs/core/MediaType;\"), (object, arguments) -> {\n        arguments.get(0).getPossibleValues().stream()\n                .map(m -> (MediaType) m).map(m -> m.getType() + '/' + m.getSubtype()).forEach(t -> addContentType(object, t));\n        return object;\n    }),\n\n    RESPONSE_BUILDER_TYPE_STRING(ofNonStatic(CLASS_RESPONSE_BUILDER, \"type\", RESPONSE_BUILDER, STRING), (object, arguments) -> {\n        arguments.get(0).getPossibleValues().stream()\n                .map(t -> (String) t).forEach(t -> addContentType(object, t));\n        return object;\n    }),\n\n    RESPONSE_BUILDER_VARIANT(ofNonStatic(CLASS_RESPONSE_BUILDER, \"variant\", RESPONSE_BUILDER, VARIANT), (object, arguments) -> {\n        addHeader(object, HttpHeaders.CONTENT_LANGUAGE);\n        addHeader(object, HttpHeaders.CONTENT_ENCODING);\n        return object;\n    }),\n\n    RESPONSE_BUILDER_VARIANTS_LIST(ofNonStatic(CLASS_RESPONSE_BUILDER, \"variants\", RESPONSE_BUILDER, LIST), (object, arguments) ->\n            addHeader(object, HttpHeaders.VARY)),\n\n    RESPONSE_BUILDER_VARIANTS_ARRAY(ofNonStatic(CLASS_RESPONSE_BUILDER, \"variants\", RESPONSE_BUILDER, \"[Ljavax/ws/rs/core/Variant;\"), (object, arguments) ->\n            addHeader(object, HttpHeaders.VARY)),\n\n    // static methods in Response --------------------------\n\n    RESPONSE_STATUS_ENUM(ofStatic(CLASS_RESPONSE, \"status\", RESPONSE_BUILDER, RESPONSE_STATUS), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    RESPONSE_STATUS_INT(ofStatic(CLASS_RESPONSE, \"status\", RESPONSE_BUILDER, PRIMITIVE_INT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    RESPONSE_OK(ofStatic(CLASS_RESPONSE, \"ok\", RESPONSE_BUILDER), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.OK.getStatusCode());\n    }),\n\n    RESPONSE_OK_ENTITY(ofStatic(CLASS_RESPONSE, \"ok\", RESPONSE_BUILDER, OBJECT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.OK.getStatusCode());\n        return addEntity(object, arguments.get(0));\n    }),\n\n    RESPONSE_OK_VARIANT(ofStatic(CLASS_RESPONSE, \"ok\", RESPONSE_BUILDER, OBJECT, VARIANT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.OK.getStatusCode());\n        addEntity(object, arguments.get(0));\n        addHeader(object, HttpHeaders.CONTENT_LANGUAGE);\n        return addHeader(object, HttpHeaders.CONTENT_ENCODING);\n    }),\n\n    RESPONSE_OK_MEDIATYPE(ofStatic(CLASS_RESPONSE, \"ok\", RESPONSE_BUILDER, OBJECT, \"Ljavax/ws/rs/core/MediaType;\"), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.OK.getStatusCode());\n        arguments.get(1).getPossibleValues().stream().map(m -> (MediaType) m)\n                .map(m -> m.getType() + '/' + m.getSubtype()).forEach(t -> addContentType(object, t));\n        return addEntity(object, arguments.get(0));\n    }),\n\n    RESPONSE_OK_MEDIATYPE_STRING(ofStatic(CLASS_RESPONSE, \"ok\", RESPONSE_BUILDER, OBJECT, STRING), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.OK.getStatusCode());\n        arguments.get(1).getPossibleValues().stream()\n                .map(t -> (String) t).forEach(t -> addContentType(object, t));\n        return addEntity(object, arguments.get(0));\n    }),\n\n    RESPONSE_ACCEPTED(ofStatic(CLASS_RESPONSE, \"accepted\", RESPONSE_BUILDER), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.ACCEPTED.getStatusCode());\n    }),\n\n    RESPONSE_ACCEPTED_ENTITY(ofStatic(CLASS_RESPONSE, \"accepted\", RESPONSE_BUILDER, OBJECT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.ACCEPTED.getStatusCode());\n        return addEntity(object, arguments.get(0));\n    }),\n\n    RESPONSE_CREATED(ofStatic(CLASS_RESPONSE, \"created\", RESPONSE_BUILDER, URI), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.CREATED.getStatusCode());\n        return addHeader(object, HttpHeaders.LOCATION);\n    }),\n\n    RESPONSE_NO_CONTENT(ofStatic(CLASS_RESPONSE, \"noContent\", RESPONSE_BUILDER), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.NO_CONTENT.getStatusCode());\n    }),\n\n    RESPONSE_NOT_ACCEPTABLE(ofStatic(CLASS_RESPONSE, \"notAcceptable\", RESPONSE_BUILDER, LIST), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.NOT_ACCEPTABLE.getStatusCode());\n        return addHeader(object, HttpHeaders.VARY);\n    }),\n\n    RESPONSE_NOT_MODIFIED(ofStatic(CLASS_RESPONSE, \"notModified\", RESPONSE_BUILDER), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.NOT_MODIFIED.getStatusCode());\n    }),\n\n    RESPONSE_NOT_MODIFIED_ENTITYTAG(ofStatic(CLASS_RESPONSE, \"notModified\", RESPONSE_BUILDER, ENTITY_TAG), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.NOT_MODIFIED.getStatusCode());\n        return addHeader(object, HttpHeaders.ETAG);\n    }),\n\n    RESPONSE_NOT_MODIFIED_ENTITYTAG_STRING(ofStatic(CLASS_RESPONSE, \"notModified\", RESPONSE_BUILDER, STRING), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.NOT_MODIFIED.getStatusCode());\n        return addHeader(object, HttpHeaders.ETAG);\n    }),\n\n    RESPONSE_SEE_OTHER(ofStatic(CLASS_RESPONSE, \"seeOther\", RESPONSE_BUILDER, URI), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.SEE_OTHER.getStatusCode());\n        return addHeader(object, HttpHeaders.LOCATION);\n    }),\n\n    RESPONSE_TEMPORARY_REDIRECT(ofStatic(CLASS_RESPONSE, \"temporaryRedirect\", RESPONSE_BUILDER, URI), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        addStatus(object, Response.Status.TEMPORARY_REDIRECT.getStatusCode());\n        return addHeader(object, HttpHeaders.LOCATION);\n    }),\n\n    RESPONSE_SERVER_ERROR(ofStatic(CLASS_RESPONSE, \"serverError\", RESPONSE_BUILDER), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());\n    }),\n\n    // WebApplicationExceptions --------------------------\n\n    WEB_APPLICATION_EXCEPTION_EMPTY(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());\n    }),\n\n    WEB_APPLICATION_EXCEPTION_RESPONSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, RESPONSE), (notAvailable, arguments) -> arguments.get(0)),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_RESPONSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, RESPONSE),\n            (notAvailable, arguments) -> arguments.get(1)),\n\n    WEB_APPLICATION_EXCEPTION_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, PRIMITIVE_INT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, PRIMITIVE_INT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(1).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_RESPONSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, RESPONSE_STATUS), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(0).getPossibleValues().stream()\n                .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_RESPONSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, RESPONSE_STATUS), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(1).getPossibleValues().stream()\n                .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_CAUSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, THROWABLE), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_CAUSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, THROWABLE), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        return addStatus(object, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());\n    }),\n\n    WEB_APPLICATION_EXCEPTION_CAUSE_RESPONSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, THROWABLE, RESPONSE),\n            (notAvailable, arguments) -> arguments.get(1)),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_CAUSE_RESPONSE(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, THROWABLE, RESPONSE),\n            (notAvailable, arguments) -> arguments.get(2)),\n\n    WEB_APPLICATION_EXCEPTION_CAUSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, THROWABLE, PRIMITIVE_INT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(1).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_CAUSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, THROWABLE, PRIMITIVE_INT), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(2).getPossibleValues().stream()\n                .map(status -> (int) status).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_CAUSE_RESPONSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, THROWABLE, RESPONSE_STATUS), (notAvailable, arguments) -> {\n        final Element object = new Element(RESPONSE, new HttpResponse());\n        arguments.get(1).getPossibleValues().stream()\n                .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n        return object;\n    }),\n\n    WEB_APPLICATION_EXCEPTION_MESSAGE_CAUSE_RESPONSE_STATUS(ofNonStatic(CLASS_WEB_APPLICATION_EXCEPTION, INITIALIZER_NAME, PRIMITIVE_VOID, STRING, THROWABLE, RESPONSE_STATUS),\n            (notAvailable, arguments) -> {\n                final Element object = new Element(RESPONSE, new HttpResponse());\n                arguments.get(2).getPossibleValues().stream()\n                        .map(status -> ((Response.Status) status).getStatusCode()).forEach(s -> addStatus(object, s));\n                return object;\n            }),\n\n    // other methods --------------------------\n\n    RESOURCE_CONTEXT_INIT(ofNonStatic(CLASS_RESOURCE_CONTEXT, \"getResource\", OBJECT, CLASS),\n            (object, arguments) -> new Element(arguments.get(0).getPossibleValues().stream()\n                    .filter(s -> s instanceof String).map(s -> (String) s).collect(Collectors.toSet()))\n    ),\n\n    RESOURCE_CONTEXT_GET(ofNonStatic(CLASS_RESOURCE_CONTEXT, \"initResource\", OBJECT, OBJECT),\n            (object, arguments) -> new Element(arguments.get(0).getTypes())),\n\n    INTEGER_VALUE_OF(ofStatic(CLASS_INTEGER, \"valueOf\", PRIMITIVE_INT, INTEGER),\n            (object, arguments) -> new Element(INTEGER, arguments.get(0).getPossibleValues().toArray())),\n\n    DOUBLE_VALUE_OF(ofStatic(CLASS_DOUBLE, \"valueOf\", PRIMITIVE_DOUBLE, DOUBLE),\n            (object, arguments) -> new Element(INTEGER, arguments.get(0).getPossibleValues().toArray())),\n\n    LONG_VALUE_OF(ofStatic(CLASS_LONG, \"valueOf\", PRIMITIVE_LONG, LONG),\n            (object, arguments) -> new Element(INTEGER, arguments.get(0).getPossibleValues().toArray())),\n\n    // stream related methods --------------------------\n\n    LIST_STREAM(ofNonStatic(CLASS_LIST, \"stream\", STREAM),\n            (object, arguments) -> new Element(object.getTypes())),\n\n    LIST_FOR_EACH(ofNonStatic(CLASS_LIST, \"forEach\", PRIMITIVE_VOID, CONSUMER), (object, arguments) -> {\n        if (arguments.get(0) instanceof MethodHandle)\n            ((Method) arguments.get(0)).invoke(null, Collections.singletonList(object));\n        return null;\n    }),\n\n    SET_STREAM(ofNonStatic(CLASS_SET, \"stream\", STREAM),\n            (object, arguments) -> new Element(object.getTypes())),\n\n    SET_FOR_EACH(ofNonStatic(CLASS_SET, \"forEach\", PRIMITIVE_VOID, CONSUMER), (object, arguments) -> {\n        if (arguments.get(0) instanceof MethodHandle)\n            ((Method) arguments.get(0)).invoke(null, Collections.singletonList(object));\n        return null;\n    }),\n\n    STREAM_COLLECT(ofNonStatic(CLASS_STREAM, \"collect\", OBJECT, SUPPLIER, BI_CONSUMER, BI_CONSUMER),\n            (object, arguments) -> {\n                if (arguments.get(0) instanceof MethodHandle && arguments.get(1) instanceof MethodHandle) {\n                    final Element collectionElement = ((Method) arguments.get(0)).invoke(null, Collections.emptyList());\n                    ((Method) arguments.get(1)).invoke(null, Arrays.asList(collectionElement, object));\n                    return collectionElement;\n                }\n                return new Element();\n            }),\n\n    STREAM_FOR_EACH(ofNonStatic(CLASS_STREAM, \"forEach\", PRIMITIVE_VOID, CONSUMER), (object, arguments) -> {\n        if (arguments.get(0) instanceof MethodHandle)\n            ((Method) arguments.get(0)).invoke(null, Collections.singletonList(object));\n        return null;\n    }),\n\n    STREAM_MAP(ofNonStatic(CLASS_STREAM, \"map\", STREAM, \"Ljava/util/function/Function;\"), (object, arguments) -> {\n        if (arguments.get(0) instanceof MethodHandle) {\n            return ((MethodHandle) arguments.get(0)).invoke(null, Collections.singletonList(object));\n        }\n        return new Element();\n    });\n\n    private final MethodIdentifier identifier;\n\n    private final BiFunction<Element, List<Element>, Element> function;\n\n    KnownResponseResultMethod(final MethodIdentifier identifier,\n                              final BiFunction<Element, List<Element>, Element> function) {\n        this.identifier = identifier;\n        this.function = function;\n    }\n\n    @Override\n    public Element invoke(final Element object, final List<Element> arguments) {\n        if (arguments.size() != identifier.getParameters().size())\n            throw new IllegalArgumentException(\"Method arguments do not match expected signature!\");\n\n        return function.apply(object, arguments);\n    }\n\n    @Override\n    public boolean matches(final MethodIdentifier identifier) {\n        return this.identifier.equals(identifier);\n    }\n\n    private static Element addHeader(final Element object, final String header) {\n        object.getPossibleValues().stream().filter(r -> r instanceof HttpResponse).map(r -> (HttpResponse) r).forEach(r -> r.getHeaders().add(header));\n        return object;\n    }\n\n    private static Element addEntity(final Element object, final Element argument) {\n        object.getPossibleValues().stream().filter(r -> r instanceof HttpResponse).map(r -> (HttpResponse) r)\n                .forEach(r -> {\n                    r.getEntityTypes().addAll(argument.getTypes());\n                    argument.getPossibleValues().stream().filter(j -> j instanceof JsonValue).map(j -> (JsonValue) j).forEach(j -> r.getInlineEntities().add(j));\n                });\n        return object;\n    }\n\n    private static Element addStatus(final Element object, final Integer status) {\n        object.getPossibleValues().stream().filter(r -> r instanceof HttpResponse).map(r -> (HttpResponse) r).forEach(r -> r.getStatuses().add(status));\n        return object;\n    }\n\n    private static Element addContentType(final Element object, final String type) {\n        object.getPossibleValues().stream().filter(r -> r instanceof HttpResponse).map(r -> (HttpResponse) r).forEach(r -> r.getContentTypes().add(type));\n        return object;\n    }\n\n}"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/simulation/MethodPool.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.IdentifiableMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.Method;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\nimport java.util.function.Function;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.PRIMITIVE_VOID;\n\n/**\n * A thread-safe singleton pool of known {@link Method}s.\n *\n * @author Sebastian Daschner\n */\npublic class MethodPool {\n\n    /**\n     * The only instance of the method pool.\n     */\n    private static final MethodPool INSTANCE = new MethodPool();\n    private static final Function<MethodIdentifier, Method> DEFAULT_METHOD = identifier -> (object, arguments) -> {\n        if (!PRIMITIVE_VOID.equals(identifier.getReturnType()))\n            return new Element(identifier.getReturnType());\n        return null;\n    };\n\n    private final List<IdentifiableMethod> availableMethods;\n    private final ReadWriteLock readWriteLock;\n\n    private MethodPool() {\n        availableMethods = new LinkedList<>();\n\n        // order matters, known methods are taken first\n        Stream.of(KnownResponseResultMethod.values()).forEach(availableMethods::add);\n        Stream.of(KnownJsonResultMethod.values()).forEach(availableMethods::add);\n\n        readWriteLock = new ReentrantReadWriteLock();\n    }\n\n    /**\n     * Adds a project method to the pool.\n     *\n     * @param method The method to add\n     */\n    public void addProjectMethod(final ProjectMethod method) {\n        readWriteLock.writeLock().lock();\n        try {\n            availableMethods.add(method);\n        } finally {\n            readWriteLock.writeLock().unlock();\n        }\n    }\n\n    /**\n     * Returns a method identified by an method identifier.\n     *\n     * @param identifier The method identifier\n     * @return The found method or a default handler\n     */\n    public Method get(final MethodIdentifier identifier) {\n        // search for available methods\n        readWriteLock.readLock().lock();\n        try {\n            final Optional<? extends IdentifiableMethod> method = availableMethods.stream().filter(m -> m.matches(identifier)).findAny();\n            if (method.isPresent())\n                return method.get();\n        } finally {\n            readWriteLock.readLock().unlock();\n        }\n\n        // apply default behaviour\n        return DEFAULT_METHOD.apply(identifier);\n    }\n\n    /**\n     * Returns the singleton instance.\n     *\n     * @return The method pool\n     */\n    public static MethodPool getInstance() {\n        return INSTANCE;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/simulation/MethodSimulator.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.MethodHandle;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.Method;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport org.objectweb.asm.Label;\n\nimport javax.ws.rs.core.MultivaluedHashMap;\nimport javax.ws.rs.core.MultivaluedMap;\nimport java.util.*;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.determineLeastSpecificType;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toType;\n\n/**\n * Simulates the instructions of a method. This class is thread-safe.\n *\n * @author Sebastian Daschner\n */\npublic class MethodSimulator {\n\n    private final Lock lock = new ReentrantLock();\n    private final MethodPool methodPool = MethodPool.getInstance();\n    private final Stack<Element> runtimeStack = new Stack<>();\n    private final MultivaluedMap<Label, Integer> variableInvalidation = new MultivaluedHashMap<>();\n    private Label active;\n\n    Map<Integer, Element> localVariables = new HashMap<>();\n\n    private Element returnElement;\n\n    /**\n     * Simulates the instructions and collects information about the resource method.\n     *\n     * @param instructions The instructions of the method\n     * @return The return element merged with all possible values\n     */\n    public Element simulate(final List<Instruction> instructions) {\n        lock.lock();\n        try {\n            returnElement = null;\n            return simulateInternal(instructions);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Simulates the instructions of the method.\n     *\n     * @param instructions The instructions to simulate\n     * @return The return element of the method\n     */\n    Element simulateInternal(final List<Instruction> instructions) {\n        instructions.forEach(this::simulate);\n\n        return returnElement;\n    }\n\n    /**\n     * Simulates the instruction.\n     *\n     * @param instruction The instruction to simulate\n     */\n    private void simulate(final Instruction instruction) {\n        switch (instruction.getType()) {\n            case PUSH:\n                final PushInstruction pushInstruction = (PushInstruction) instruction;\n                runtimeStack.push(new Element(pushInstruction.getValueType(), pushInstruction.getValue()));\n                break;\n            case METHOD_HANDLE:\n                simulateMethodHandle((InvokeDynamicInstruction) instruction);\n                break;\n            case INVOKE:\n                simulateInvoke((InvokeInstruction) instruction);\n                break;\n            case GET_FIELD:\n                runtimeStack.pop();\n                runtimeStack.push(new Element(((GetFieldInstruction) instruction).getPropertyType()));\n                break;\n            case GET_STATIC:\n                final GetStaticInstruction getStaticInstruction = (GetStaticInstruction) instruction;\n                final Object value = getStaticInstruction.getValue();\n                if (value != null)\n                    runtimeStack.push(new Element(getStaticInstruction.getPropertyType(), value));\n                else\n                    runtimeStack.push(new Element(getStaticInstruction.getPropertyType()));\n                break;\n            case LOAD:\n                final LoadInstruction loadInstruction = (LoadInstruction) instruction;\n                runtimeStack.push(localVariables.getOrDefault(loadInstruction.getNumber(), new Element(loadInstruction.getVariableType())));\n                runtimeStack.peek().getTypes().add(loadInstruction.getVariableType());\n                variableInvalidation.add(loadInstruction.getValidUntil(), loadInstruction.getNumber());\n                break;\n            case STORE:\n                simulateStore((StoreInstruction) instruction);\n                break;\n            case SIZE_CHANGE:\n                simulateSizeChange((SizeChangingInstruction) instruction);\n                break;\n            case NEW:\n                final NewInstruction newInstruction = (NewInstruction) instruction;\n                runtimeStack.push(new Element(toType(newInstruction.getClassName())));\n                break;\n            case DUP:\n                runtimeStack.push(runtimeStack.peek());\n                break;\n            case OTHER:\n                // do nothing\n                break;\n            case RETURN:\n                mergeReturnElement(runtimeStack.pop());\n            case THROW:\n                mergePossibleResponse();\n                // stack has to be empty for further analysis\n                runtimeStack.clear();\n                break;\n            default:\n                throw new IllegalArgumentException(\"Instruction without type!\");\n        }\n\n        if (instruction.getLabel() != active && variableInvalidation.containsKey(active)) {\n            variableInvalidation.get(active).forEach(localVariables::remove);\n        }\n        active = instruction.getLabel();\n    }\n\n    /**\n     * Simulates the invoke dynamic call. Pushes a method handle on the stack.\n     *\n     * @param instruction The instruction to simulate\n     */\n    private void simulateMethodHandle(final InvokeDynamicInstruction instruction) {\n        final List<Element> arguments = IntStream.range(0, instruction.getDynamicIdentifier().getParameters().size())\n                .mapToObj(t -> runtimeStack.pop()).collect(Collectors.toList());\n        Collections.reverse(arguments);\n\n        if (!instruction.getDynamicIdentifier().isStaticMethod())\n            // first parameter is `this`\n            arguments.remove(0);\n\n        // adds the transferred arguments of the bootstrap call\n        runtimeStack.push(new MethodHandle(instruction.getDynamicIdentifier().getReturnType(), instruction.getIdentifier(), arguments));\n    }\n\n    /**\n     * Simulates the invoke instruction.\n     *\n     * @param instruction The instruction to simulate\n     */\n    private void simulateInvoke(final InvokeInstruction instruction) {\n        final List<Element> arguments = new LinkedList<>();\n        MethodIdentifier identifier = instruction.getIdentifier();\n\n        IntStream.range(0, identifier.getParameters().size()).forEach(i -> arguments.add(runtimeStack.pop()));\n        Collections.reverse(arguments);\n\n        Element object = null;\n        Method method;\n        if (!identifier.isStaticMethod()) {\n            object = runtimeStack.pop();\n            if (object instanceof MethodHandle) {\n                method = (Method) object;\n            } else {\n                method = methodPool.get(identifier);\n            }\n        } else {\n            method = methodPool.get(identifier);\n        }\n        final Element returnedElement = method.invoke(object, arguments);\n        if (returnedElement != null)\n            runtimeStack.push(returnedElement);\n        else if (!identifier.getReturnType().equals(Types.PRIMITIVE_VOID))\n            runtimeStack.push(new Element(identifier.getReturnType()));\n    }\n\n    /**\n     * Simulates the store instruction.\n     *\n     * @param instruction The instruction to simulate\n     */\n    private void simulateStore(final StoreInstruction instruction) {\n        final int index = instruction.getNumber();\n        final Element elementToStore = runtimeStack.pop();\n\n        if (elementToStore instanceof MethodHandle)\n            mergeMethodHandleStore(index, (MethodHandle) elementToStore);\n        else\n            mergeElementStore(index, instruction.getVariableType(), elementToStore);\n    }\n\n    /**\n     * Merges a stored element to the local variables.\n     *\n     * @param index   The index of the variable\n     * @param type    The type of the variable or the element (whatever is more specific)\n     * @param element The element to merge\n     */\n    private void mergeElementStore(final int index, final String type, final Element element) {\n        // new element must be created for immutability\n        final String elementType = type.equals(Types.OBJECT) ? determineLeastSpecificType(element.getTypes().toArray(new String[element.getTypes().size()])) : type;\n        final Element created = new Element(elementType);\n        created.merge(element);\n        localVariables.merge(index, created, Element::merge);\n    }\n\n    /**\n     * Merges a stored method handle to the local variables.\n     *\n     * @param index        The index of the variable\n     * @param methodHandle The method handle to merge\n     */\n    private void mergeMethodHandleStore(final int index, final MethodHandle methodHandle) {\n        localVariables.merge(index, new MethodHandle(methodHandle), Element::merge);\n    }\n\n    /**\n     * Checks if the current stack element is eligible for being merged with the returned element.\n     */\n    private void mergePossibleResponse() {\n        // TODO only HttpResponse element?\n        if (!runtimeStack.isEmpty() && runtimeStack.peek().getTypes().contains(Types.RESPONSE)) {\n            mergeReturnElement(runtimeStack.peek());\n        }\n    }\n\n    /**\n     * Simulates the size change instruction.\n     *\n     * @param instruction The instruction to simulate\n     */\n    private void simulateSizeChange(final SizeChangingInstruction instruction) {\n        IntStream.range(0, instruction.getNumberOfPops()).forEach(i -> runtimeStack.pop());\n        IntStream.range(0, instruction.getNumberOfPushes()).forEach(i -> runtimeStack.push(new Element()));\n    }\n\n    /**\n     * Merges the {@code returnElement} with the given element which was popped from the stack.\n     * If the {@code returnElement} existed before, the values are merged.\n     *\n     * @param stackElement The popped element\n     */\n    private void mergeReturnElement(final Element stackElement) {\n        if (returnElement != null)\n            stackElement.merge(returnElement);\n        returnElement = stackElement;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/ContextClassReader.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport org.objectweb.asm.ClassReader;\n\nimport java.io.IOException;\nimport java.net.URL;\nimport java.net.URLClassLoader;\n\n/**\n * A {@link ClassReader} that is able to use a separate {@link ClassLoader}.\n *\n * @author Sebastian Daschner\n */\npublic class ContextClassReader extends ClassReader {\n\n    private static final ExtensibleClassLoader CLASS_LOADER = new ExtensibleClassLoader();\n\n    public ContextClassReader(final String className) throws IOException {\n        super(CLASS_LOADER.getResourceAsStream(className.replace('.', '/') + \".class\"));\n    }\n\n    public static ClassLoader getClassLoader() {\n        return CLASS_LOADER;\n    }\n\n    public static void addClassPath(final URL url) {\n        CLASS_LOADER.addURL(url);\n    }\n\n    private static class ExtensibleClassLoader extends URLClassLoader {\n\n        ExtensibleClassLoader() {\n            super(new URL[]{});\n        }\n\n        @Override\n        public void addURL(final URL url) {\n            super.addURL(url);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSAnnotatedSuperMethodClassVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Type;\n\nimport java.lang.reflect.Method;\n\nimport static org.objectweb.asm.Opcodes.*;\n\n/**\n * @author Sebastian Daschner\n */\nclass JAXRSAnnotatedSuperMethodClassVisitor extends ClassVisitor {\n\n    private final MethodResult methodResult;\n    private final Method method;\n\n    JAXRSAnnotatedSuperMethodClassVisitor(final MethodResult methodResult, final Method method) {\n        super(ASM5);\n        this.methodResult = methodResult;\n        this.method = method;\n    }\n\n    @Override\n    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {\n        final boolean legalModifiers = ((access & ACC_SYNTHETIC) | (access & ACC_STATIC) | (access & ACC_NATIVE)) == 0;\n\n        final String descriptor = Type.getMethodDescriptor(method);\n        if (legalModifiers && method.getName().equals(name) && (descriptor.equals(desc) || descriptor.equals(signature)))\n            return new JAXRSAnnotatedSuperMethodVisitor(methodResult);\n\n        return null;\n    }\n\n}\n\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSAnnotatedSuperMethodVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport java.util.BitSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.objectweb.asm.Opcodes.ASM5;\n\n/**\n * @author Sebastian Daschner\n */\nclass JAXRSAnnotatedSuperMethodVisitor extends MethodVisitor {\n\n    private final MethodResult methodResult;\n    private final List<String> parameterTypes;\n    private final Map<Integer, MethodParameter> methodParameters;\n    private final BitSet annotatedParameters;\n\n    JAXRSAnnotatedSuperMethodVisitor(final MethodResult methodResult) {\n        super(ASM5);\n        this.methodResult = methodResult;\n        parameterTypes = methodResult.getOriginalMethodSignature().getParameters();\n        annotatedParameters = new BitSet(parameterTypes.size());\n        methodParameters = new HashMap<>();\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        switch (desc) {\n            case Types.GET:\n                methodResult.setHttpMethod(HttpMethod.GET);\n                break;\n            case Types.POST:\n                methodResult.setHttpMethod(HttpMethod.POST);\n                break;\n            case Types.PUT:\n                methodResult.setHttpMethod(HttpMethod.PUT);\n                break;\n            case Types.DELETE:\n                methodResult.setHttpMethod(HttpMethod.DELETE);\n                break;\n            case Types.HEAD:\n                methodResult.setHttpMethod(HttpMethod.HEAD);\n                break;\n            case Types.OPTIONS:\n                methodResult.setHttpMethod(HttpMethod.OPTIONS);\n                break;\n            case Types.DEPRECATED:\n                methodResult.setDeprecated(true);\n                break;\n            case Types.PATH:\n                return new PathAnnotationVisitor(methodResult);\n            case Types.CONSUMES:\n                return new ConsumesAnnotationVisitor(methodResult);\n            case Types.PRODUCES:\n                return new ProducesAnnotationVisitor(methodResult);\n        }\n        return null;\n    }\n\n    @Override\n    public AnnotationVisitor visitParameterAnnotation(final int index, final String annotationDesc, final boolean visible) {\n        switch (annotationDesc) {\n            case Types.PATH_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.PATH);\n            case Types.QUERY_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.QUERY);\n            case Types.HEADER_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.HEADER);\n            case Types.FORM_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.FORM);\n            case Types.COOKIE_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.COOKIE);\n            case Types.MATRIX_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.MATRIX);\n            case Types.DEFAULT_VALUE:\n                return defaultAnnotationVisitor(index);\n            case Types.SUSPENDED:\n                LogProvider.debug(\"Handling of \" + annotationDesc + \" not yet implemented\");\n            case Types.CONTEXT:\n                annotatedParameters.set(index);\n            default:\n                return null;\n        }\n    }\n\n    private AnnotationVisitor paramAnnotationVisitor(final int index, final ParameterType parameterType) {\n        annotatedParameters.set(index);\n        final String type = parameterTypes.get(index);\n\n        MethodParameter methodParameter = methodParameters.get(index);\n        if (methodParameter == null) {\n            methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);\n            methodParameters.put(index, methodParameter);\n        } else {\n            methodParameter.setParameterType(parameterType);\n        }\n\n        return new ParamAnnotationVisitor(methodParameter);\n    }\n\n    private AnnotationVisitor defaultAnnotationVisitor(final int index) {\n        final String type = parameterTypes.get(index);\n\n        MethodParameter methodParameter = methodParameters.get(index);\n        if (methodParameter == null) {\n            methodParameter = new MethodParameter(TypeIdentifier.ofType(type));\n            methodParameters.put(index, methodParameter);\n        }\n\n        return new DefaultValueAnnotationVisitor(methodParameter);\n    }\n\n    @Override\n    public void visitEnd() {\n        if (annotatedParameters.cardinality() != parameterTypes.size()) {\n            final String requestBodyType = parameterTypes.get(annotatedParameters.nextClearBit(0));\n            methodResult.setRequestBodyType(requestBodyType);\n        }\n        methodResult.getMethodParameters().addAll(methodParameters.values());\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSClassVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.ApplicationPathAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.ConsumesAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.PathAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.ProducesAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.*;\n\nimport javax.ws.rs.*;\nimport java.io.IOException;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Method;\nimport java.util.*;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.isAnnotationPresent;\nimport static org.objectweb.asm.Opcodes.*;\n\n/**\n * @author Sebastian Daschner\n */\npublic class JAXRSClassVisitor extends ClassVisitor {\n\n    private static final Class<? extends Annotation>[] RELEVANT_METHOD_ANNOTATIONS = new Class[]{Path.class, GET.class, PUT.class, POST.class, DELETE.class, OPTIONS.class, HEAD.class};\n\n    private final ClassResult classResult;\n\n    public JAXRSClassVisitor(final ClassResult classResult) {\n        super(ASM5);\n        this.classResult = classResult;\n    }\n\n    @Override\n    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {\n        classResult.setOriginalClass(name);\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        switch (desc) {\n            case Types.PATH:\n                return new PathAnnotationVisitor(classResult);\n            case Types.APPLICATION_PATH:\n                return new ApplicationPathAnnotationVisitor(classResult);\n            case Types.CONSUMES:\n                return new ConsumesAnnotationVisitor(classResult);\n            case Types.PRODUCES:\n                return new ProducesAnnotationVisitor(classResult);\n            case Types.DEPRECATED:\n                classResult.setDeprecated(true);\n                break;\n        }\n        return null;\n    }\n\n    @Override\n    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {\n        if ((access & ACC_STATIC) == 0)\n            return new JAXRSFieldVisitor(classResult, desc, signature);\n        return null;\n    }\n\n    @Override\n    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {\n        final boolean legalModifiers = ((access & ACC_SYNTHETIC) | (access & ACC_STATIC) | (access & ACC_NATIVE)) == 0;\n        final String methodSignature = signature == null ? desc : signature;\n        final MethodIdentifier identifier = MethodIdentifier.of(classResult.getOriginalClass(), name, methodSignature, false);\n\n        if (legalModifiers && !\"<init>\".equals(name)) {\n            final MethodResult methodResult = new MethodResult();\n            if (hasJAXRSAnnotations(classResult.getOriginalClass(), name, methodSignature))\n                return new JAXRSMethodVisitor(identifier, classResult, methodResult, true);\n            else {\n                final Method annotatedSuperMethod = searchAnnotatedSuperMethod(classResult.getOriginalClass(), name, methodSignature);\n                if (annotatedSuperMethod != null) {\n                    try {\n                        return new JAXRSMethodVisitor(identifier, classResult, methodResult, false);\n                    } finally {\n                        classResult.getMethods().stream().filter(m -> m.equals(methodResult)).findAny().ifPresent(m -> visitJAXRSSuperMethod(annotatedSuperMethod, m));\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    private static boolean hasJAXRSAnnotations(final String className, final String methodName, final String signature) {\n        final Method method = JavaUtils.findMethod(className, methodName, signature);\n        return method != null && hasJAXRSAnnotations(method);\n    }\n\n    private static Method searchAnnotatedSuperMethod(final String className, final String methodName, final String methodSignature) {\n        final List<Class<?>> superTypes = determineSuperTypes(className);\n        return superTypes.stream().map(c -> {\n            final Method superAnnotatedMethod = JavaUtils.findMethod(c, methodName, methodSignature);\n            if (superAnnotatedMethod != null && hasJAXRSAnnotations(superAnnotatedMethod))\n                return superAnnotatedMethod;\n            return null;\n        }).filter(Objects::nonNull).findAny().orElse(null);\n    }\n\n    private static List<Class<?>> determineSuperTypes(final String className) {\n        final Class<?> loadedClass = JavaUtils.loadClassFromName(className);\n        if (loadedClass == null)\n            return Collections.emptyList();\n\n        final List<Class<?>> superClasses = new ArrayList<>();\n        final Queue<Class<?>> classesToCheck = new LinkedBlockingQueue<>();\n        Class<?> currentClass = loadedClass;\n\n        do {\n            if (currentClass.getSuperclass() != null && Object.class != currentClass.getSuperclass())\n                classesToCheck.add(currentClass.getSuperclass());\n\n            Stream.of(currentClass.getInterfaces()).forEach(classesToCheck::add);\n\n            if (currentClass != loadedClass)\n                superClasses.add(currentClass);\n\n        } while ((currentClass = classesToCheck.poll()) != null);\n\n        return superClasses;\n    }\n\n    private static boolean hasJAXRSAnnotations(final Method method) {\n        for (final Object annotation : method.getDeclaredAnnotations()) {\n            // TODO test both\n            if (Stream.of(RELEVANT_METHOD_ANNOTATIONS).map(a -> JavaUtils.getAnnotation(method, a))\n                    .filter(Objects::nonNull).anyMatch(a -> a.getClass().isAssignableFrom(annotation.getClass())))\n                return true;\n\n            if (isAnnotationPresent(annotation.getClass(), HttpMethod.class))\n                return true;\n        }\n        return false;\n    }\n\n    private void visitJAXRSSuperMethod(Method method, MethodResult methodResult) {\n        try {\n\n            final ClassReader classReader = new ContextClassReader(method.getDeclaringClass().getCanonicalName());\n            final ClassVisitor visitor = new JAXRSAnnotatedSuperMethodClassVisitor(methodResult, method);\n\n            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n        } catch (IOException e) {\n            LogProvider.error(\"Could not analyze JAX-RS super annotated method \" + method);\n            LogProvider.debug(e);\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSFieldVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.DefaultValueAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.ParamAnnotationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objectweb.asm.Opcodes;\n\n/**\n * @author Sebastian Daschner\n */\nclass JAXRSFieldVisitor extends FieldVisitor {\n\n    private final ClassResult classResult;\n    private final String signature;\n    private MethodParameter parameter;\n\n    JAXRSFieldVisitor(final ClassResult classResult, final String desc, final String signature) {\n        super(Opcodes.ASM5);\n        this.classResult = classResult;\n        this.signature = signature == null ? desc : signature;\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {\n        switch (desc) {\n            case Types.PATH_PARAM:\n                return paramAnnotationVisitor(ParameterType.PATH);\n            case Types.QUERY_PARAM:\n                return paramAnnotationVisitor(ParameterType.QUERY);\n            case Types.HEADER_PARAM:\n                return paramAnnotationVisitor(ParameterType.HEADER);\n            case Types.FORM_PARAM:\n                return paramAnnotationVisitor(ParameterType.FORM);\n            case Types.COOKIE_PARAM:\n                return paramAnnotationVisitor(ParameterType.COOKIE);\n            case Types.MATRIX_PARAM:\n                return paramAnnotationVisitor(ParameterType.MATRIX);\n            case Types.DEFAULT_VALUE:\n                return defaultAnnotationVisitor();\n            default:\n                return null;\n        }\n    }\n\n    private AnnotationVisitor paramAnnotationVisitor(final ParameterType parameterType) {\n        if (parameter == null)\n            parameter = new MethodParameter(TypeIdentifier.ofType(signature), parameterType);\n        else\n            parameter.setParameterType(parameterType);\n        return new ParamAnnotationVisitor(parameter);\n    }\n\n    private AnnotationVisitor defaultAnnotationVisitor() {\n        if (parameter == null)\n            parameter = new MethodParameter(TypeIdentifier.ofType(signature));\n        return new DefaultValueAnnotationVisitor(parameter);\n    }\n\n    @Override\n    public void visitEnd() {\n        if (parameter != null)\n            classResult.getClassFields().add(parameter);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSMethodVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.InstructionBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.Opcodes;\n\nimport java.util.BitSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author Sebastian Daschner\n */\nclass JAXRSMethodVisitor extends ProjectMethodVisitor {\n\n    private final List<String> parameterTypes;\n    private final Map<Integer, MethodParameter> methodParameters;\n    private final BitSet annotatedParameters;\n    private final boolean methodAnnotated;\n\n    JAXRSMethodVisitor(final MethodIdentifier identifier, final ClassResult classResult, final MethodResult methodResult, final boolean methodAnnotated) {\n        super(methodResult, identifier.getContainingClass());\n        this.methodAnnotated = methodAnnotated;\n\n        parameterTypes = identifier.getParameters();\n        annotatedParameters = new BitSet(parameterTypes.size());\n        methodParameters = new HashMap<>();\n\n        methodResult.setOriginalMethodSignature(identifier);\n        classResult.add(methodResult);\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        switch (desc) {\n            case Types.GET:\n                methodResult.setHttpMethod(HttpMethod.GET);\n                break;\n            case Types.POST:\n                methodResult.setHttpMethod(HttpMethod.POST);\n                break;\n            case Types.PUT:\n                methodResult.setHttpMethod(HttpMethod.PUT);\n                break;\n            case Types.DELETE:\n                methodResult.setHttpMethod(HttpMethod.DELETE);\n                break;\n            case Types.HEAD:\n                methodResult.setHttpMethod(HttpMethod.HEAD);\n                break;\n            case Types.OPTIONS:\n                methodResult.setHttpMethod(HttpMethod.OPTIONS);\n                break;\n            case Types.DEPRECATED:\n                methodResult.setDeprecated(true);\n                break;\n            case Types.PATH:\n                return new PathAnnotationVisitor(methodResult);\n            case Types.CONSUMES:\n                return new ConsumesAnnotationVisitor(methodResult);\n            case Types.PRODUCES:\n                return new ProducesAnnotationVisitor(methodResult);\n        }\n        return null;\n    }\n\n    @Override\n    public AnnotationVisitor visitParameterAnnotation(final int index, final String annotationDesc, final boolean visible) {\n        switch (annotationDesc) {\n            case Types.PATH_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.PATH);\n            case Types.QUERY_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.QUERY);\n            case Types.HEADER_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.HEADER);\n            case Types.FORM_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.FORM);\n            case Types.COOKIE_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.COOKIE);\n            case Types.MATRIX_PARAM:\n                return paramAnnotationVisitor(index, ParameterType.MATRIX);\n            case Types.DEFAULT_VALUE:\n                return defaultAnnotationVisitor(index);\n            case Types.SUSPENDED:\n                LogProvider.debug(\"Handling of \" + annotationDesc + \" not yet implemented\");\n            case Types.CONTEXT:\n                annotatedParameters.set(index);\n            default:\n                return null;\n        }\n    }\n\n    private AnnotationVisitor paramAnnotationVisitor(final int index, final ParameterType parameterType) {\n        annotatedParameters.set(index);\n        final String type = parameterTypes.get(index);\n\n        MethodParameter methodParameter = methodParameters.get(index);\n        if (methodParameter == null) {\n            methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);\n            methodParameters.put(index, methodParameter);\n        } else {\n            methodParameter.setParameterType(parameterType);\n        }\n\n        return new ParamAnnotationVisitor(methodParameter);\n    }\n\n    private AnnotationVisitor defaultAnnotationVisitor(final int index) {\n        final String type = parameterTypes.get(index);\n\n        MethodParameter methodParameter = methodParameters.computeIfAbsent(index, i -> new MethodParameter(TypeIdentifier.ofType(type)));\n\n        return new DefaultValueAnnotationVisitor(methodParameter);\n    }\n\n    @Override\n    public void visitEnd() {\n        super.visitEnd();\n        // determine request body parameter\n        if (methodAnnotated) {\n            if (annotatedParameters.cardinality() != parameterTypes.size()) {\n                final String requestBodyType = parameterTypes.get(annotatedParameters.nextClearBit(0));\n                methodResult.setRequestBodyType(requestBodyType);\n            }\n            methodResult.getMethodParameters().addAll(methodParameters.values());\n\n            final Class<?> containingClass = JavaUtils.loadClassFromName(methodResult.getOriginalMethodSignature().getContainingClass());\n\n            if (containingClass != null && containingClass.isInterface()) {\n                methodResult.getInstructions().add(InstructionBuilder.buildInstruction(Opcodes.ICONST_0, null));\n                methodResult.getInstructions().add(InstructionBuilder.buildInstruction(Opcodes.ARETURN, null));\n            }\n        }\n\n        // TODO determine potential super methods which are annotated with JAX-RS annotations.\n        if (methodResult.getHttpMethod() == null) {\n            // method is a sub resource locator\n            final ClassResult classResult = new ClassResult();\n            methodResult.setSubResource(classResult);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/ProjectMethodClassVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport java.io.IOException;\n\nimport static org.objectweb.asm.Opcodes.*;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ProjectMethodClassVisitor extends ClassVisitor {\n\n    private final MethodResult methodResult;\n    private final MethodIdentifier identifier;\n    private boolean methodFound;\n    private String superName;\n\n    public ProjectMethodClassVisitor(final MethodResult methodResult, final MethodIdentifier identifier) {\n        super(ASM5);\n        this.methodResult = methodResult;\n        this.identifier = identifier;\n    }\n\n    @Override\n    public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {\n        this.superName = superName;\n    }\n\n    @Override\n    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {\n        // TODO allow abstract?\n        final boolean legalModifiers = (access & ACC_ABSTRACT | access & ACC_NATIVE) == 0;\n\n        final String methodSignature = identifier.getSignature();\n        if (legalModifiers && identifier.getMethodName().equals(name) && (methodSignature.equals(desc) || methodSignature.equals(signature))) {\n            methodFound = true;\n            return new ProjectMethodVisitor(methodResult, identifier.getContainingClass());\n        }\n\n        return null;\n    }\n\n    @Override\n    public void visitEnd() {\n        // if method hasn't been found it may be on a super class (invoke_virtual)\n        if (!methodFound && !superName.equals(Types.CLASS_OBJECT)) {\n            try {\n                final ClassReader classReader = new ContextClassReader(superName);\n                final ClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, identifier);\n\n                classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n            } catch (IOException e) {\n                LogProvider.error(\"Could not analyze project method \" + superName + \"#\" + identifier.getMethodName());\n                LogProvider.debug(e);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/ProjectMethodVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Type;\n\nimport java.util.*;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.InstructionBuilder.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction.InstructionType.LOAD_PLACEHOLDER;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction.InstructionType.STORE_PLACEHOLDER;\nimport static org.objectweb.asm.Opcodes.*;\nimport static org.objectweb.asm.util.Printer.OPCODES;\n\n/**\n * @author Sebastian Daschner\n */\nclass ProjectMethodVisitor extends MethodVisitor {\n\n    private final Set<Label> exceptionHandlers = new HashSet<>();\n    private final List<Label> visitedLabels = new ArrayList<>();\n    final MethodResult methodResult;\n    private final String className;\n\n    ProjectMethodVisitor(MethodResult methodResult, String className) {\n        super(ASM5);\n        // TODO refactor to list of instructions only\n        this.methodResult = methodResult;\n        this.className = className;\n    }\n\n    @Override\n    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {\n        exceptionHandlers.add(handler);\n    }\n\n    @Override\n    public void visitLabel(Label label) {\n        visitedLabels.add(label);\n        if (exceptionHandlers.remove(label))\n            methodResult.getInstructions().add(new ExceptionHandlerInstruction(label));\n    }\n\n    @Override\n    public void visitMaxs(final int maxStack, final int maxLocals) {\n        super.visitMaxs(maxStack, maxLocals);\n    }\n\n    @Override\n    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {\n        // resolve LOAD & STORE placeholders\n        ListIterator<Instruction> iterator = methodResult.getInstructions().listIterator();\n        while (iterator.hasNext()) {\n            final Instruction instruction = iterator.next();\n            if (instruction.getType() != LOAD_PLACEHOLDER && instruction.getType() != STORE_PLACEHOLDER)\n                continue;\n\n            final LoadStoreInstructionPlaceholder placeholder = (LoadStoreInstructionPlaceholder) instruction;\n            if (placeholder.getNumber() != index)\n                continue;\n\n            final Label label = placeholder.getLabel();\n            if (isLabelActive(label, start, end)) {\n                final String type = signature != null ? signature : desc;\n                iterator.set(placeholder.getType() == LOAD_PLACEHOLDER ? new LoadInstruction(index, type, name, label, end) : new StoreInstruction(index, type, name, label));\n            }\n        }\n    }\n\n    private boolean isLabelActive(final Label label, final Label start, final Label end) {\n        boolean startVisited = false;\n        for (final Label current : visitedLabels) {\n            if (current == start)\n                startVisited = true;\n            if (current == label)\n                return startVisited;\n            if (current == end)\n                return false;\n        }\n        return false;\n    }\n\n    @Override\n    public void visitInsn(int opcode) {\n        methodResult.getInstructions().add(buildInstruction(opcode, getLastLabel()));\n    }\n\n    @Override\n    public void visitIntInsn(int opcode, int operand) {\n        methodResult.getInstructions().add(buildIntInstruction(opcode, operand, getLastLabel()));\n    }\n\n    @Override\n    public void visitVarInsn(int opcode, int index) {\n        final Label label = !visitedLabels.isEmpty() ? visitedLabels.get(visitedLabels.size() - 1) : null;\n        methodResult.getInstructions().add(buildLoadStoreInstruction(opcode, index, label));\n    }\n\n    @Override\n    public void visitTypeInsn(int opcode, String className) {\n        methodResult.getInstructions().add(buildTypeInstruction(opcode, className, getLastLabel()));\n    }\n\n    @Override\n    public void visitFieldInsn(int opcode, String owner, String name, String desc) {\n        methodResult.getInstructions().add(buildFieldInstruction(opcode, owner, name, desc, getLastLabel()));\n    }\n\n    @Override\n    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {\n        methodResult.getInstructions().add(buildInvokeInstruction(opcode, owner, name, desc, getLastLabel()));\n    }\n\n    @Override\n    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {\n        final Handle handle = Stream.of(bsmArgs).filter(a -> a instanceof Handle).map(a -> (Handle) a)\n                .findAny().orElse(bsm);\n\n        methodResult.getInstructions().add(buildInvokeDynamic(className, name, desc, handle, getLastLabel()));\n    }\n\n    @Override\n    public void visitJumpInsn(int opcode, Label label) {\n        methodResult.getInstructions().add(buildJumpInstruction(opcode, label));\n    }\n\n    @Override\n    public void visitLdcInsn(Object object) {\n        methodResult.getInstructions().add(createLdcInstruction(object, getLastLabel()));\n    }\n\n    private Label getLastLabel() {\n        if (visitedLabels.isEmpty())\n            return null;\n        return visitedLabels.get(visitedLabels.size() - 1);\n    }\n\n    private PushInstruction createLdcInstruction(final Object object, final Label label) {\n        // see MethodVisitor\n        if (object instanceof Integer) {\n            return new PushInstruction(object, Types.INTEGER, label);\n        }\n        if (object instanceof Float) {\n            return new PushInstruction(object, Types.FLOAT, label);\n        }\n        if (object instanceof Long) {\n            return new PushInstruction(object, Types.LONG, label);\n        }\n        if (object instanceof Double) {\n            return new PushInstruction(object, Types.DOUBLE, label);\n        }\n        if (object instanceof String) {\n            return new PushInstruction(object, Types.STRING, label);\n        }\n        if (object instanceof Type) {\n            return new PushInstruction(((Type) object).getDescriptor(), Types.CLASS, label);\n        }\n        return new PushInstruction(object, Type.getDescriptor(object.getClass()), label);\n    }\n\n    @Override\n    public void visitIincInsn(int var, int increment) {\n        methodResult.getInstructions().add(new DefaultInstruction(OPCODES[IINC], getLastLabel()));\n    }\n\n    @Override\n    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {\n        methodResult.getInstructions().add(new SizeChangingInstruction(OPCODES[TABLESWITCH], 0, 1, getLastLabel()));\n    }\n\n    @Override\n    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {\n        methodResult.getInstructions().add(new SizeChangingInstruction(OPCODES[LOOKUPSWITCH], 0, 1, getLastLabel()));\n    }\n\n    @Override\n    public void visitMultiANewArrayInsn(String desc, int dimensions) {\n        methodResult.getInstructions().add(new SizeChangingInstruction(OPCODES[MULTIANEWARRAY], 1, dimensions, getLastLabel()));\n    }\n\n    @Override\n    public void visitEnd() {\n        // resolve unresolved placeholders\n        final ListIterator<Instruction> listIterator = methodResult.getInstructions().listIterator();\n        while (listIterator.hasNext()) {\n            final Instruction instruction = listIterator.next();\n            if (instruction.getType() == LOAD_PLACEHOLDER) {\n                listIterator.set(new LoadInstruction(((LoadStoreInstructionPlaceholder) instruction).getNumber(), Types.OBJECT, instruction.getLabel(), null));\n            } else if (instruction.getType() == STORE_PLACEHOLDER) {\n                listIterator.set(new StoreInstruction(((LoadStoreInstructionPlaceholder) instruction).getNumber(), Types.OBJECT, instruction.getLabel()));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ApplicationPathAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ApplicationPathAnnotationVisitor extends ValueAnnotationVisitor {\n\n    private final ClassResult classResult;\n\n    public ApplicationPathAnnotationVisitor(final ClassResult classResult) {\n        this.classResult = classResult;\n    }\n\n    @Override\n    protected void visitValue(final String value) {\n        classResult.setApplicationPath(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ClassAndMethodAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.Objects;\n\n/**\n * @author Sebastian Daschner\n */\nabstract class ClassAndMethodAnnotationVisitor extends ValueAnnotationVisitor {\n\n    private final ClassResult classResult;\n    private final MethodResult methodResult;\n\n    ClassAndMethodAnnotationVisitor(final ClassResult classResult) {\n        this(classResult, null);\n        Objects.requireNonNull(classResult);\n    }\n\n    ClassAndMethodAnnotationVisitor(final MethodResult methodResult) {\n        this(null, methodResult);\n        Objects.requireNonNull(methodResult);\n    }\n\n    private ClassAndMethodAnnotationVisitor(final ClassResult classResult, final MethodResult methodResult) {\n        this.classResult = classResult;\n        this.methodResult = methodResult;\n    }\n\n    protected abstract void visitValue(String value, ClassResult classResult);\n\n    protected abstract void visitValue(String value, MethodResult methodResult);\n\n    @Override\n    protected final void visitValue(final String value) {\n        if (classResult != null)\n            visitValue(value, classResult);\n        else\n            visitValue(value, methodResult);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ConsumesAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ConsumesAnnotationVisitor extends ClassAndMethodAnnotationVisitor {\n\n    public ConsumesAnnotationVisitor(final ClassResult classResult) {\n        super(classResult);\n    }\n\n    public ConsumesAnnotationVisitor(final MethodResult methodResult) {\n        super(methodResult);\n    }\n\n    @Override\n    protected void visitValue(final String value, final ClassResult classResult) {\n        classResult.getRequestMediaTypes().add(value);\n    }\n\n    @Override\n    protected void visitValue(final String value, final MethodResult methodResult) {\n        methodResult.getRequestMediaTypes().add(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/DefaultValueAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\n\n/**\n * Visits the {@link javax.ws.rs.DefaultValue} annotation and sets the configured value.\n *\n * @author Daryl Teo\n * @author Sebastian Daschner\n */\npublic class DefaultValueAnnotationVisitor extends ValueAnnotationVisitor {\n\n    private final MethodParameter parameter;\n\n    public DefaultValueAnnotationVisitor(final MethodParameter parameter) {\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected void visitValue(String value) {\n        parameter.setDefaultValue(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ParamAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ParamAnnotationVisitor extends ValueAnnotationVisitor {\n\n    private final MethodParameter parameter;\n\n    public ParamAnnotationVisitor(final MethodParameter parameter) {\n        this.parameter = parameter;\n    }\n\n    @Override\n    protected void visitValue(final String value) {\n        parameter.setName(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/PathAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\n/**\n * @author Sebastian Daschner\n */\npublic class PathAnnotationVisitor extends ClassAndMethodAnnotationVisitor {\n\n    public PathAnnotationVisitor(final ClassResult classResult) {\n        super(classResult);\n    }\n\n    public PathAnnotationVisitor(final MethodResult methodResult) {\n        super(methodResult);\n    }\n\n    @Override\n    protected void visitValue(final String value, final ClassResult classResult) {\n        classResult.setResourcePath(value);\n    }\n\n    @Override\n    protected void visitValue(final String value, final MethodResult methodResult) {\n        methodResult.setPath(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ProducesAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ProducesAnnotationVisitor extends ClassAndMethodAnnotationVisitor {\n\n    public ProducesAnnotationVisitor(final ClassResult classResult) {\n        super(classResult);\n    }\n\n    public ProducesAnnotationVisitor(final MethodResult methodResult) {\n        super(methodResult);\n    }\n\n    @Override\n    protected void visitValue(final String value, final ClassResult classResult) {\n        classResult.getResponseMediaTypes().add(value);\n    }\n\n    @Override\n    protected void visitValue(final String value, final MethodResult methodResult) {\n        methodResult.getResponseMediaTypes().add(value);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/annotation/ValueAnnotationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.annotation;\n\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.Opcodes;\n\n/**\n * @author Sebastian Daschner\n */\nabstract class ValueAnnotationVisitor extends AnnotationVisitor {\n\n    private static final String NAME = \"value\";\n\n    ValueAnnotationVisitor() {\n        super(Opcodes.ASM5);\n    }\n\n    protected abstract void visitValue(String value);\n\n    @Override\n    public void visit(String name, Object value) {\n        if (NAME.equals(name)) {\n            visitValue((String) value);\n        }\n    }\n\n    @Override\n    public AnnotationVisitor visitArray(String name) {\n        return new AnnotationVisitor(Opcodes.ASM5) {\n            @Override\n            public void visit(String name, Object value) {\n                visitValue((String) value);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/javadoc/JavaDocAnalyzer.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.javadoc;\n\nimport com.github.javaparser.JavaParser;\nimport com.github.javaparser.ast.CompilationUnit;\nimport com.github.javaparser.ast.body.MethodDeclaration;\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.nio.file.FileVisitResult;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.SimpleFileVisitor;\nimport java.nio.file.attribute.BasicFileAttributes;\nimport java.util.*;\nimport java.util.stream.Stream;\n\n/**\n * @author Sebastian Daschner\n */\npublic class JavaDocAnalyzer {\n\n    private final Map<MethodIdentifier, MethodComment> methodComments = new HashMap<>();\n\n    public void analyze(final Set<Path> projectSourcePaths, final Set<ClassResult> classResults) {\n        invokeParser(projectSourcePaths);\n        combineResults(classResults);\n    }\n\n    private void invokeParser(Set<Path> projectSourcePaths) {\n        try {\n            for (Path projectSourcePath : projectSourcePaths) {\n                invokeParser(projectSourcePath);\n            }\n        } catch (IOException e) {\n            LogProvider.error(\"could not analyze JavaDoc, reason: \" + e.getMessage());\n            LogProvider.debug(e);\n        }\n    }\n\n    private void invokeParser(Path sourcePath) throws IOException {\n        Set<Path> files = new HashSet<>();\n\n        Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {\n            @Override\n            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {\n                if (file.toString().endsWith(\".java\"))\n                    files.add(file);\n                return super.visitFile(file, attrs);\n            }\n        });\n\n        files.forEach(path -> parseJavaDoc(path, new JavaDocParserVisitor(methodComments)));\n    }\n\n    private static void parseJavaDoc(Path path, JavaDocParserVisitor visitor) {\n        try {\n            CompilationUnit cu = JavaParser.parse(path.toFile());\n            cu.accept(visitor, null);\n        } catch (FileNotFoundException e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    private void combineResults(final Set<ClassResult> classResults) {\n        methodComments.forEach((key, value) -> classResults.stream()\n                .map(c -> findMethodResult(key, c))\n                .filter(Objects::nonNull)\n                .forEach(m -> m.setMethodDoc(value)));\n    }\n\n    private MethodResult findMethodResult(final MethodIdentifier identifier, final ClassResult classResult) {\n        if (classResult.getOriginalClass().equals(identifier.getContainingClass()))\n            return classResult.getMethods().stream()\n                    .filter(methodResult -> equalsSimpleTypeNames(identifier, methodResult))\n                    .findAny().orElse(null);\n\n        return classResult.getMethods().stream()\n                .map(MethodResult::getSubResource)\n                .filter(Objects::nonNull)\n                .map(c -> findMethodResult(identifier, c))\n                .filter(Objects::nonNull)\n                .findAny().orElse(null);\n    }\n\n    /**\n     * This is a best-effort approach combining only the simple types.\n     *\n     * @see JavaDocParserVisitor#calculateMethodIdentifier(MethodDeclaration)\n     */\n    private boolean equalsSimpleTypeNames(MethodIdentifier identifier, MethodResult methodResult) {\n        MethodIdentifier originalIdentifier = methodResult.getOriginalMethodSignature();\n\n        return originalIdentifier.getMethodName().equals(identifier.getMethodName()) &&\n                matchesTypeBestEffort(originalIdentifier.getReturnType(), identifier.getReturnType()) &&\n                parameterMatch(originalIdentifier.getParameters(), identifier.getParameters());\n    }\n\n    private boolean parameterMatch(List<String> originalTypes, List<String> types) {\n        if (originalTypes.size() != types.size())\n            return false;\n        for (int i = 0; i < originalTypes.size(); i++) {\n            if (!matchesTypeBestEffort(originalTypes.get(i), types.get(i)))\n                return false;\n        }\n        return true;\n    }\n\n    private boolean matchesTypeBestEffort(String originalType, String type) {\n        // if types are generic types, use full original type signature\n        if (type.contains(\"<\"))\n            return Stream.of(type.replace(\">\", \"\").split(\"<\")).allMatch(originalType::contains);\n        // otherwise use class name (for primitives)\n        return JavaUtils.toClassName(originalType).contains(type);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/javadoc/JavaDocParserVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.javadoc;\n\nimport com.github.javaparser.ast.NodeList;\nimport com.github.javaparser.ast.PackageDeclaration;\nimport com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;\nimport com.github.javaparser.ast.body.FieldDeclaration;\nimport com.github.javaparser.ast.body.MethodDeclaration;\nimport com.github.javaparser.ast.body.Parameter;\nimport com.github.javaparser.ast.comments.Comment;\nimport com.github.javaparser.ast.expr.AnnotationExpr;\nimport com.github.javaparser.ast.expr.Expression;\nimport com.github.javaparser.ast.expr.NameExpr;\nimport com.github.javaparser.ast.expr.StringLiteralExpr;\nimport com.github.javaparser.ast.visitor.VoidVisitorAdapter;\nimport com.github.javaparser.javadoc.Javadoc;\nimport com.github.javaparser.javadoc.JavadocBlockTag;\nimport com.github.javaparser.javadoc.description.JavadocDescription;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.ClassComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MemberParameterTag;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.ofNonStatic;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.ofStatic;\n\n/**\n * @author Sebastian Daschner\n */\npublic class JavaDocParserVisitor extends VoidVisitorAdapter<Void> {\n\n    private String packageName;\n    private String className;\n    private final Map<MethodIdentifier, MethodComment> methodComments;\n    private final Map<String, ClassComment> classComments = new HashMap<>();\n\n    public JavaDocParserVisitor(Map<MethodIdentifier, MethodComment> methodComments) {\n        this.methodComments = methodComments;\n    }\n\n    @Override\n    public void visit(PackageDeclaration packageDeclaration, Void arg) {\n        packageName = packageDeclaration.getNameAsString();\n        super.visit(packageDeclaration, arg);\n    }\n\n    @Override\n    public void visit(ClassOrInterfaceDeclaration classOrInterface, Void arg) {\n        className = calculateClassName(classOrInterface);\n\n        classOrInterface.getComment()\n                .filter(Comment::isJavadocComment)\n                .map(this::toJavaDoc)\n                .ifPresent(this::recordClassComment);\n\n        super.visit(classOrInterface, arg);\n    }\n\n    private Javadoc toJavaDoc(Comment comment) {\n        return comment.asJavadocComment().parse();\n    }\n\n    private boolean isDeprecated(Javadoc javadoc) {\n        return javadoc.getBlockTags().stream().anyMatch(t -> t.getType() == JavadocBlockTag.Type.DEPRECATED);\n    }\n\n    private String calculateClassName(ClassOrInterfaceDeclaration classOrInterface) {\n        if (StringUtils.isBlank(packageName))\n            return classOrInterface.getNameAsString();\n        return packageName.replace('.', '/') + \"/\" + classOrInterface.getNameAsString();\n    }\n\n    private void recordClassComment(Javadoc javadoc) {\n        String comment = javadoc.getDescription().toText();\n        Map<Integer, String> responseComments = createResponseComments(javadoc);\n        classComments.put(className, new ClassComment(comment, responseComments, isDeprecated(javadoc)));\n    }\n\n    @Override\n    public void visit(FieldDeclaration field, Void arg) {\n        field.getComment()\n                .filter(Comment::isJavadocComment)\n                .map(this::toJavaDoc)\n                .ifPresent(c -> createFieldComment(c, field));\n        super.visit(field, arg);\n    }\n\n    private void createFieldComment(Javadoc javadoc, FieldDeclaration field) {\n        ClassComment classComment = classComments.get(className);\n        if (classComment == null) {\n            classComment = new ClassComment();\n            classComments.put(className, classComment);\n        }\n        classComment.getFieldComments().add(createMemberParamTag(javadoc.getDescription(), field.getAnnotations().stream()));\n    }\n\n    @Override\n    public void visit(MethodDeclaration method, Void arg) {\n        method.getComment()\n                .filter(Comment::isJavadocComment)\n                .map(this::toJavaDoc)\n                .ifPresent(c -> recordMethodComment(c, method));\n        super.visit(method, arg);\n    }\n\n    private void recordMethodComment(Javadoc javadoc, MethodDeclaration method) {\n        MethodIdentifier identifier = calculateMethodIdentifier(method);\n        String comment = javadoc.getDescription().toText();\n        List<MemberParameterTag> tags = createMethodParameterTags(javadoc, method);\n        Map<Integer, String> responseComments = createResponseComments(javadoc);\n        methodComments.put(identifier, new MethodComment(comment, tags, responseComments, classComments.get(className), isDeprecated(javadoc)));\n    }\n\n    private List<MemberParameterTag> createMethodParameterTags(Javadoc javadoc, MethodDeclaration method) {\n        return javadoc.getBlockTags().stream()\n                .filter(t -> t.getType() == JavadocBlockTag.Type.PARAM)\n                .map(t -> createMethodParameterTag(t, method))\n                .collect(Collectors.toList());\n    }\n\n    private MemberParameterTag createMethodParameterTag(JavadocBlockTag tag, MethodDeclaration method) {\n        Stream<AnnotationExpr> annotations = method.getParameterByName(tag.getName().orElse(null))\n                .map(Parameter::getAnnotations)\n                .map(NodeList::stream)\n                .orElseGet(Stream::empty);\n\n        return createMemberParamTag(tag.getContent(), annotations);\n    }\n\n    private MemberParameterTag createMemberParamTag(JavadocDescription javadocDescription, Stream<AnnotationExpr> annotationStream) {\n        Map<String, String> annotations = annotationStream\n                .filter(Expression::isSingleMemberAnnotationExpr)\n                .collect(Collectors.toMap(a -> a.getName().getIdentifier(),\n                        this::createMemberParamValue));\n        return new MemberParameterTag(javadocDescription.toText(), annotations);\n    }\n\n    private String createMemberParamValue(AnnotationExpr a) {\n        Expression memberValue = a.asSingleMemberAnnotationExpr().getMemberValue();\n        if (memberValue.getClass().isAssignableFrom(StringLiteralExpr.class))\n            return memberValue.asStringLiteralExpr().asString();\n\n        if (memberValue.getClass().isAssignableFrom(NameExpr.class))\n            return memberValue.asNameExpr().getNameAsString();\n\n        throw new IllegalArgumentException(String.format(\"Javadoc param type (%s) not supported.\", memberValue.toString()));\n    }\n\n    private Map<Integer, String> createResponseComments(Javadoc javadoc) {\n        return javadoc.getBlockTags().stream()\n                .filter(t -> ResponseCommentExtractor.RESPONSE_TAG_NAME.equalsIgnoreCase(t.getTagName()))\n                .map(t -> t.getContent().toText())\n                .map(ResponseCommentExtractor::extract)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toMap(Pair::getLeft, Pair::getRight));\n    }\n\n    /**\n     * <b>Note:</b> This will not return the actual identifier but only the simple names of the types (return type &amp; parameter types).\n     * Doing a full type resolving with all imports adds too much complexity at this point.\n     * This is a best-effort approach.\n     */\n    private MethodIdentifier calculateMethodIdentifier(MethodDeclaration method) {\n        String[] parameters = method.getParameters().stream()\n                .map(p -> p.getType().asString())\n                .map(p -> p.replace('.', '/'))\n                .toArray(String[]::new);\n        String returnType = method.getType().asString().replace('.', '/');\n\n        if (method.isStatic()) {\n            return ofStatic(className, method.getNameAsString(), returnType, parameters);\n        }\n        return ofNonStatic(className, method.getNameAsString(), returnType, parameters);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/javadoc/ResponseCommentExtractor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.javadoc;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\n\nclass ResponseCommentExtractor {\n\n    private ResponseCommentExtractor() {\n    }\n\n    static final String RESPONSE_TAG_NAME = \"response\";\n\n    static Pair<Integer, String> extract(String comment) {\n        try {\n            String commentText = comment.trim();\n            String statusPart = commentText.split(\"\\\\s\")[0];\n            int status = Integer.parseInt(statusPart);\n            return Pair.of(status, commentText.substring(statusPart.length()).trim());\n        } catch (Exception e) {\n            LogProvider.info(\"Warning: malformed @response JavaDoc tag: '@response \" + comment + \"'\");\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/DynamicTypeAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.json.JsonArray;\nimport javax.json.JsonObject;\nimport javax.json.JsonValue;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Analyzes {@code JsonValue}s to derive the actual JSON representations.\n * Equal JSON structures (i.e. objects or arrays) will result in the same dynamically identified representation.\n *\n * @author Sebastian Daschner\n */\nclass DynamicTypeAnalyzer {\n\n    /**\n     * The type representation storage where all analyzed types have to be added. This will be created by the caller.\n     */\n    private final Map<TypeIdentifier, TypeRepresentation> typeRepresentations;\n\n    DynamicTypeAnalyzer(final Map<TypeIdentifier, TypeRepresentation> typeRepresentations) {\n        this.typeRepresentations = typeRepresentations;\n    }\n\n    /**\n     * Analyzes the given JSON value.\n     *\n     * @param jsonValue The JSON value to analyze\n     * @return The type identifier\n     */\n    TypeIdentifier analyze(final JsonValue jsonValue) {\n        return analyzeInternal(jsonValue);\n    }\n\n    private TypeIdentifier analyzeInternal(final JsonValue jsonValue) {\n        switch (jsonValue.getValueType()) {\n            case ARRAY:\n                return analyzeInternal((JsonArray) jsonValue);\n            case OBJECT:\n                return analyzeInternal((JsonObject) jsonValue);\n            case STRING:\n                return TypeIdentifier.ofType(Types.STRING);\n            case NUMBER:\n                return TypeIdentifier.ofType(Types.DOUBLE);\n            case TRUE:\n            case FALSE:\n                return TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN);\n            case NULL:\n                return TypeIdentifier.ofType(Types.OBJECT);\n            default:\n                throw new IllegalArgumentException(\"Unknown JSON value type provided\");\n        }\n    }\n\n    private TypeIdentifier analyzeInternal(final JsonArray jsonArray) {\n        final TypeIdentifier containedIdentifier = jsonArray.isEmpty() ? TypeIdentifier.ofType(Types.OBJECT) : analyzeInternal(jsonArray.get(0));\n        final TypeRepresentation containedRepresentation = typeRepresentations.getOrDefault(containedIdentifier, TypeRepresentation.ofConcrete(containedIdentifier));\n\n        final TypeIdentifier existingCollection = findExistingCollection(containedRepresentation);\n        if (existingCollection != null) {\n            return existingCollection;\n        }\n\n        final TypeIdentifier identifier = TypeIdentifier.ofDynamic();\n        typeRepresentations.put(identifier, TypeRepresentation.ofCollection(identifier, containedRepresentation));\n        return identifier;\n    }\n\n    private TypeIdentifier analyzeInternal(final JsonObject jsonObject) {\n        final HashMap<String, TypeIdentifier> properties = jsonObject.entrySet().stream()\n                .collect(HashMap::new, (m, v) -> m.put(v.getKey(), analyze(v.getValue())), Map::putAll);\n\n        final TypeIdentifier existing = findExistingType(properties);\n        if (existing != null)\n            return existing;\n\n        final TypeIdentifier identifier = TypeIdentifier.ofDynamic();\n        typeRepresentations.put(identifier, TypeRepresentation.ofConcrete(identifier, properties));\n        return identifier;\n    }\n\n    private TypeIdentifier findExistingCollection(final TypeRepresentation containedRepresentation) {\n        return typeRepresentations.entrySet().stream().filter(e -> e.getValue() instanceof TypeRepresentation.CollectionTypeRepresentation)\n                .filter(e -> e.getKey().getType().equals(Types.JSON))\n                .filter(e -> ((TypeRepresentation.CollectionTypeRepresentation) e.getValue()).contentEquals(containedRepresentation))\n                .map(Map.Entry::getKey).findAny().orElse(null);\n    }\n\n    private TypeIdentifier findExistingType(final HashMap<String, TypeIdentifier> properties) {\n        return typeRepresentations.entrySet().stream().filter(e -> e.getValue() instanceof TypeRepresentation.ConcreteTypeRepresentation)\n                .filter(e -> e.getKey().getType().equals(Types.JSON))\n                .filter(e -> ((TypeRepresentation.ConcreteTypeRepresentation) e.getValue()).contentEquals(properties))\n                .map(Map.Entry::getKey).findAny().orElse(null);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/JavaDocParameterResolver.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.ClassComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MemberParameterTag;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\n\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\n/**\n * Resolves the actual {@code *Param} parameters analyzed by both the JavaDoc and Bytecode analysis.\n *\n * @author Sebastian Daschner\n */\nfinal class JavaDocParameterResolver {\n\n    private static final String[] KNOWN_ANNOTATIONS = {PATH_PARAM, QUERY_PARAM, HEADER_PARAM, FORM_PARAM, COOKIE_PARAM, MATRIX_PARAM, DEFAULT_VALUE, SUSPENDED, CONTEXT};\n\n    private JavaDocParameterResolver() {\n        throw new UnsupportedOperationException();\n    }\n\n    static Optional<MemberParameterTag> findParameterDoc(final MethodParameter parameter, final MethodComment methodDoc) {\n        return methodDoc.getParamTags().stream()\n                .filter(p -> hasAnnotation(parameter, p.getAnnotations()))\n                .findAny();\n    }\n\n    static Optional<MemberParameterTag> findFieldDoc(final MethodParameter parameter, final ClassComment classDoc) {\n        if (classDoc == null)\n            return Optional.empty();\n\n        return classDoc.getFieldComments().stream()\n                .filter(f -> hasAnnotation(parameter, f.getAnnotations()))\n                .findAny();\n    }\n\n    static Optional<MemberParameterTag> findRequestBodyDoc(final MethodComment methodDoc) {\n        return methodDoc.getParamTags().stream()\n                .filter(p -> isRequestBody(p.getAnnotations()))\n                .findAny();\n    }\n\n    private static boolean hasAnnotation(final MethodParameter parameter, final Map<String, String> annotations) {\n        return annotations.entrySet().stream()\n                .filter(e -> annotationTypeMatches(e.getKey(), parameter.getParameterType()))\n                .anyMatch(e -> Objects.equals(e.getValue(), parameter.getName()));\n    }\n\n    private static boolean isRequestBody(final Map<String, String> annotations) {\n        return annotations.entrySet().stream()\n                .noneMatch(e -> findKnownAnnotation(e.getKey()));\n    }\n\n    private static boolean findKnownAnnotation(String simpleTypeName) {\n        return Stream.of(KNOWN_ANNOTATIONS).anyMatch(a -> a.contains(simpleTypeName));\n    }\n\n    private static boolean annotationTypeMatches(final String qualifiedTypeName, final ParameterType parameterType) {\n        String javaType = getJavaType(parameterType);\n        return javaType != null && javaType.contains(qualifiedTypeName);\n    }\n\n    private static String getJavaType(final ParameterType parameterType) {\n        switch (parameterType) {\n            case PATH:\n                return toReadableType(PATH_PARAM);\n            case QUERY:\n                return toReadableType(QUERY_PARAM);\n            case HEADER:\n                return toReadableType(HEADER_PARAM);\n            case FORM:\n                return toReadableType(FORM_PARAM);\n            case MATRIX:\n                return toReadableType(MATRIX_PARAM);\n            case COOKIE:\n                return toReadableType(COOKIE_PARAM);\n            default:\n                return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/JavaTypeAnalyzer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonIgnoreType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\nimport org.objectweb.asm.Type;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport javax.xml.bind.annotation.XmlElement;\nimport javax.xml.bind.annotation.XmlTransient;\nimport java.lang.reflect.*;\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.COLLECTION;\n\n/**\n * Analyzes a class (usually a POJO) for it's properties and methods.\n * The analysis is used to derive the JSON/XML representations.\n *\n * @author Sebastian Daschner\n */\nclass JavaTypeAnalyzer {\n\n    private final static String[] NAMES_TO_IGNORE = {\"getClass\"};\n    private static Set<String> ignoredFieldNames = new HashSet<>();\n\n    /**\n     * The type representation storage where all analyzed types have to be added. This will be created by the caller.\n     */\n    private final Map<TypeIdentifier, TypeRepresentation> typeRepresentations;\n    private final Set<String> analyzedTypes;\n\n    JavaTypeAnalyzer(final Map<TypeIdentifier, TypeRepresentation> typeRepresentations) {\n        this.typeRepresentations = typeRepresentations;\n        analyzedTypes = new HashSet<>();\n    }\n\n    /**\n     * Analyzes the given type. Resolves known generics and creates a representation of the contained class, all contained properties\n     * and nested types recursively.\n     *\n     * @param rootType The type to analyze\n     * @return The (root) type identifier\n     */\n    // TODO consider arrays\n    TypeIdentifier analyze(final String rootType) {\n        final String type = ResponseTypeNormalizer.normalizeResponseWrapper(rootType);\n        final TypeIdentifier identifier = TypeIdentifier.ofType(type);\n\n        if (!analyzedTypes.contains(type) && (isAssignableTo(type, COLLECTION) || !isJDKType(type))) {\n            analyzedTypes.add(type);\n            typeRepresentations.put(identifier, analyzeInternal(identifier, type));\n        }\n\n        return identifier;\n    }\n\n    private static boolean isJDKType(final String type) {\n        // exclude java, javax, etc. packages\n        return Types.PRIMITIVE_TYPES.contains(type) || type.startsWith(\"Ljava/\") || type.startsWith(\"Ljavax/\");\n    }\n\n    private TypeRepresentation analyzeInternal(final TypeIdentifier identifier, final String type) {\n        if (isAssignableTo(type, COLLECTION)) {\n            final String containedType = ResponseTypeNormalizer.normalizeCollection(type);\n            return TypeRepresentation.ofCollection(identifier, analyzeInternal(TypeIdentifier.ofType(containedType), containedType));\n        }\n\n        final Class<?> loadedClass = loadClassFromType(type);\n        if (loadedClass != null && loadedClass.isEnum())\n            return TypeRepresentation.ofEnum(identifier, Stream.of(loadedClass.getEnumConstants()).map(o -> (Enum<?>) o).map(Enum::name).toArray(String[]::new));\n\n        return TypeRepresentation.ofConcrete(identifier, analyzeClass(type, loadedClass));\n    }\n\n    private Map<String, TypeIdentifier> analyzeClass(final String type, final Class<?> clazz) {\n        if (clazz == null || isJDKType(type))\n            return Collections.emptyMap();\n\n        final XmlAccessType value = getXmlAccessType(clazz);\n\n        // TODO analyze & test annotation inheritance\n        ignoredFieldNames.clear();\n        final List<Field> relevantFields = Stream.of(clazz.getDeclaredFields()).filter(f -> isRelevant(f, value)).collect(Collectors.toList());\n        final List<Method> relevantGetters = Stream.of(clazz.getDeclaredMethods()).filter(m -> isRelevant(m, value)).collect(Collectors.toList());\n\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final Stream<Class<?>> allSuperTypes = Stream.concat(Stream.of(clazz.getInterfaces()), Stream.of(clazz.getSuperclass()));\n        allSuperTypes.filter(Objects::nonNull).map(Type::getDescriptor).map(t -> analyzeClass(t, loadClassFromType(t))).forEach(properties::putAll);\n\n        Stream.concat(relevantFields.stream().map(f -> mapField(f, type)), relevantGetters.stream().map(g -> mapGetter(g, type)))\n                .filter(Objects::nonNull).forEach(p -> {\n            properties.put(p.getLeft(), TypeIdentifier.ofType(p.getRight()));\n            analyze(p.getRight());\n        });\n\n        return properties;\n    }\n\n    private XmlAccessType getXmlAccessType(final Class<?> clazz) {\n        Class<?> current = clazz;\n\n        while (current != null) {\n            if (isAnnotationPresent(current, XmlAccessorType.class))\n                return getAnnotation(current, XmlAccessorType.class).value();\n            current = current.getSuperclass();\n        }\n\n        return XmlAccessType.PUBLIC_MEMBER;\n    }\n\n    private static boolean isRelevant(final Field field, final XmlAccessType accessType) {\n        if (field.isSynthetic())\n            return false;\n\n        if (hasIgnoreAnnotation(field) || isTypeIgnored(field.getType())) {\n            ignoredFieldNames.add(field.getName());\n            return false;\n        }\n\n        if (isAnnotationPresent(field, XmlElement.class))\n            return true;\n\n        final int modifiers = field.getModifiers();\n        if (accessType == XmlAccessType.FIELD)\n            // always take, unless static or transient\n            return !Modifier.isTransient(modifiers) && !Modifier.isStatic(modifiers) && !isAnnotationPresent(field, XmlTransient.class);\n        else if (accessType == XmlAccessType.PUBLIC_MEMBER)\n            // only for public, non-static\n            return Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && !isAnnotationPresent(field, XmlTransient.class);\n\n        return false;\n    }\n\n    private static <T extends AccessibleObject & Member> boolean hasIgnoreAnnotation(final T member) {\n        return isAnnotationPresent(member, JsonIgnore.class) || isTypeIgnored(member.getDeclaringClass());\n    }\n\n    private static boolean isTypeIgnored(final Class<?> declaringClass) {\n        return isAnnotationPresent(declaringClass, JsonIgnoreType.class);\n    }\n\n    /**\n     * Checks if the method is public and non-static and that the method is a Getter.\n     * Does not allow methods with ignored names.\n     * Does also not take methods annotated with {@link XmlTransient}.\n     *\n     * @param method The method\n     * @return {@code true} if the method should be analyzed further\n     */\n    private static boolean isRelevant(final Method method, final XmlAccessType accessType) {\n        if (method.isSynthetic() || !isGetter(method))\n            return false;\n\n        final boolean propertyIgnored = ignoredFieldNames.contains(extractPropertyName(method.getName()));\n        if (propertyIgnored || hasIgnoreAnnotation(method) || isTypeIgnored(method.getReturnType())) {\n            return false;\n        }\n\n        if (isAnnotationPresent(method, XmlElement.class))\n            return true;\n\n        if (accessType == XmlAccessType.PROPERTY)\n            return !isAnnotationPresent(method, XmlTransient.class);\n        else if (accessType == XmlAccessType.PUBLIC_MEMBER)\n            return Modifier.isPublic(method.getModifiers()) && !isAnnotationPresent(method, XmlTransient.class);\n\n        return false;\n    }\n\n    /**\n     * Converts a getter name to the property name (without the \"get\" or \"is\" and lowercase).\n     *\n     * @param name The name of the method (MUST match \"get[A-Z][A-Za-z]*|is[A-Z][A-Za-z]*\")\n     * @return The name of the property\n     */\n    private static String extractPropertyName(final String name) {\n        final int size = name.startsWith(\"is\") ? 2 : 3;\n        final char chars[] = name.substring(size).toCharArray();\n        chars[0] = Character.toLowerCase(chars[0]);\n        return new String(chars);\n    }\n\n    private static boolean isGetter(final Method method) {\n        if (Modifier.isStatic(method.getModifiers()))\n            return false;\n\n        final String name = method.getName();\n        if (Stream.of(NAMES_TO_IGNORE).anyMatch(n -> n.equals(name)))\n            return false;\n\n        if (name.startsWith(\"get\") && name.length() > 3)\n            return method.getReturnType() != void.class;\n\n        return name.startsWith(\"is\") && name.length() > 2 && method.getReturnType() == boolean.class;\n    }\n\n    private static Pair<String, String> mapField(final Field field, final String containedType) {\n        final String type = getFieldDescriptor(field, containedType);\n        if (type == null)\n            return null;\n\n        return Pair.of(field.getName(), type);\n    }\n\n    private static Pair<String, String> mapGetter(final Method method, final String containedType) {\n        final String returnType = getReturnType(getMethodSignature(method), containedType);\n        if (returnType == null)\n            return null;\n\n        return Pair.of(extractPropertyName(method.getName()), returnType);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/JsonMapper.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.json.JsonObjectBuilder;\nimport java.util.Set;\nimport java.util.function.Function;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\n/**\n * Creates JSON-P Json objects from the internal {@link JsonValue}s and maps JSON types.\n * The possible values of the {@link Element}s get lost.\n *\n * @author Sebastian Daschner\n */\nfinal class JsonMapper {\n\n    private JsonMapper() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Creates a JSON-P JsonValue from the internal {@link JsonValue}.\n     *\n     * @param jsonValue The JSON value to map\n     * @return A JSON-P value\n     */\n    static javax.json.JsonValue map(final JsonValue jsonValue) {\n        if (jsonValue instanceof JsonArray)\n            return map((JsonArray) jsonValue);\n        return map((JsonObject) jsonValue);\n    }\n\n    private static javax.json.JsonArray map(final JsonArray jsonArray) {\n        final JsonArrayBuilder builder = Json.createArrayBuilder();\n        jsonArray.getElements().stream().forEach(e -> addToArray(builder, e));\n        return builder.build();\n    }\n\n    private static void addToArray(final JsonArrayBuilder builder, final Element value) {\n        if (value.getTypes().contains(STRING))\n            builder.add(\"string\");\n\n        if (value.getTypes().stream().anyMatch(INTEGER_TYPES::contains))\n            builder.add(0);\n\n        if (value.getTypes().stream().anyMatch(DOUBLE_TYPES::contains))\n            builder.add(0.0);\n\n        if (value.getTypes().contains(BOOLEAN) || value.getTypes().contains(PRIMITIVE_BOOLEAN))\n            builder.add(false);\n\n        if (value.getTypes().stream().anyMatch(JSON_TYPES::contains))\n            value.getPossibleValues().stream().filter(v -> v instanceof JsonValue).findFirst().ifPresent(v -> builder.add(map((JsonValue) v)));\n    }\n\n    private static javax.json.JsonObject map(final JsonObject jsonObject) {\n        final JsonObjectBuilder builder = Json.createObjectBuilder();\n        jsonObject.getStructure().entrySet().stream().forEach(e -> addToObject(builder, e.getKey(), e.getValue()));\n        return builder.build();\n    }\n\n    private static void addToObject(final JsonObjectBuilder builder, final String key, final Element value) {\n        // handle nested JSON\n        if (value.getTypes().stream().anyMatch(JSON_TYPES::contains)) {\n            value.getPossibleValues().stream().filter(v -> v instanceof JsonValue).findFirst().ifPresent(v -> builder.add(key, map((JsonValue) v)));\n            return;\n        }\n\n        addToObject(builder, key, value.getTypes());\n    }\n\n    private static void addToObject(final JsonObjectBuilder builder, final String key, final Set<String> types) {\n        if (types.contains(STRING))\n            builder.add(key, \"string\");\n\n        if (types.stream().anyMatch(INTEGER_TYPES::contains))\n            builder.add(key, 0);\n\n        if (types.stream().anyMatch(DOUBLE_TYPES::contains))\n            builder.add(key, 0.0);\n\n        if (types.contains(BOOLEAN) || types.contains(PRIMITIVE_BOOLEAN))\n            builder.add(key, false);\n    }\n\n    // TODO remove unused code, refactor & test types (e.g. Date, JSR-310)\n    static void addToObject(final JsonObjectBuilder builder, final String key, final String type, final Function<String, javax.json.JsonValue> defaultBehavior) {\n        if (STRING.equals(type)) {\n            builder.add(key, \"string\");\n            return;\n        }\n\n        if (BOOLEAN.equals(type) || PRIMITIVE_BOOLEAN.equals(type)) {\n            builder.add(key, false);\n            return;\n        }\n\n        // TODO\n//        if (INTEGER_TYPES.contains(type)) {\n//            builder.add(key, 0);\n//            return;\n//        }\n//\n//        if (DOUBLE_TYPES.contains(type)) {\n//            builder.add(key, 0.0);\n//            return;\n//        }\n//\n//        // plain-old date and JSR-310\n//        if (type.isAssignableTo(DATE) || type.isAssignableTo(TEMPORAL_ACCESSOR)) {\n//            builder.add(key, \"date\");\n//            return;\n//        }\n//\n//        if (type.isAssignableTo(MAP)) {\n//            builder.add(key, Json.createObjectBuilder().build());\n//            return;\n//        }\n\n        // fall-back\n        builder.add(key, defaultBehavior.apply(type));\n    }\n\n    static void addToArray(final JsonArrayBuilder builder, final String type, final Function<String, javax.json.JsonValue> defaultBehavior) {\n        if (STRING.equals(type)) {\n            builder.add(\"string\");\n            return;\n        }\n\n        if (BOOLEAN.equals(type) || PRIMITIVE_BOOLEAN.equals(type)) {\n            builder.add(false);\n            return;\n        }\n\n//        if (INTEGER_TYPES.contains(type)) {\n//            builder.add(0);\n//            return;\n//        }\n//\n//        if (DOUBLE_TYPES.contains(type)) {\n//            builder.add(0.0);\n//            return;\n//        }\n\n        builder.add(defaultBehavior.apply(type));\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/PathNormalizer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\n/**\n * Normalizes the JAX-RS paths.\n *\n * @author Sebastian Daschner\n */\nfinal class PathNormalizer {\n\n    private PathNormalizer() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Returns the normalized application path found in any of the given class results.\n     *\n     * @return The base URI of the application\n     */\n    static String getApplicationPath(final Set<ClassResult> classResults) {\n        return classResults.stream().map(ClassResult::getApplicationPath).filter(Objects::nonNull)\n                .map(PathNormalizer::normalize).findAny().orElse(\"\");\n    }\n\n    /**\n     * Returns the normalized path (without forward-slashes at the beginning or the end) of the given method result\n     * including all parent class resources.\n     *\n     * @param methodResult The method result\n     * @return The normalized full path of the method\n     */\n    static String getPath(final MethodResult methodResult) {\n        final List<String> paths = determinePaths(methodResult);\n\n        return paths.stream().map(PathNormalizer::normalize).collect(Collectors.joining(\"/\"));\n    }\n\n    /**\n     * Determines all single paths of the method result recursively. All parent class and method results are analyzed as well.\n     *\n     * @param methodResult The method result\n     * @return All single path pieces\n     */\n    private static List<String> determinePaths(final MethodResult methodResult) {\n        final List<String> paths = new LinkedList<>();\n        MethodResult currentMethod = methodResult;\n\n        while (true) {\n            addNonBlank(currentMethod.getPath(), paths);\n            final ClassResult parentClass = currentMethod.getParentResource();\n\n            if (parentClass == null)\n                break;\n\n            currentMethod = parentClass.getParentSubResourceLocator();\n            if (currentMethod == null) {\n                addNonBlank(parentClass.getResourcePath(), paths);\n                break;\n            }\n        }\n\n        Collections.reverse(paths);\n        return paths;\n    }\n\n    /**\n     * Adds the string to the list if it is not blank.\n     *\n     * @param string  The string to add\n     * @param strings The list\n     */\n    private static void addNonBlank(final String string, final List<String> strings) {\n        if (!StringUtils.isBlank(string) && !\"/\".equals(string))\n            strings.add(string);\n    }\n\n    /**\n     * Normalizes the given path, i.e. trims leading or trailing forward-slashes and removes path parameter matchers.\n     *\n     * @param path The path to normalize\n     * @return The normalized path\n     */\n    private static String normalize(final String path) {\n        final StringBuilder builder = new StringBuilder(path);\n\n        int index = 0;\n        int colonIndex = -1;\n        char current = 0;\n        char last;\n\n        while ((index > -1) && (index < builder.length())) {\n            last = current;\n            current = builder.charAt(index);\n\n            switch (current) {\n                case '}':\n                    if (last == '\\\\')\n                        break;\n                    if (colonIndex != -1) {\n                        builder.delete(colonIndex, index);\n                        index = colonIndex;\n                        colonIndex = -1;\n                    }\n                    break;\n                case ':':\n                    if (colonIndex == -1) {\n                        colonIndex = index;\n                    }\n                    break;\n            }\n\n            if ((index == 0 || index == builder.length() - 1) && current == '/') {\n                builder.deleteCharAt(index);\n                if (index == builder.length()) {\n                    // check again for path end\n                    index--;\n                }\n            } else {\n                index++;\n            }\n        }\n\n        return builder.toString();\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/ResponseTypeNormalizer.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.ws.rs.core.GenericEntity;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.getTypeParameters;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.isAssignableTo;\n\n/**\n * Normalizes the request/response body Java types.\n *\n * @author Sebastian Daschner\n */\nfinal class ResponseTypeNormalizer {\n\n    private ResponseTypeNormalizer() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Normalizes the contained collection type.\n     *\n     * @param type The type\n     * @return The normalized type\n     */\n    static String normalizeCollection(final String type) {\n        if (isAssignableTo(type, Types.COLLECTION)) {\n            if (!getTypeParameters(type).isEmpty()) {\n                return getTypeParameters(type).get(0);\n            }\n            return Types.OBJECT;\n        }\n        return type;\n    }\n\n    /**\n     * Normalizes the body type (e.g. removes nested {@link GenericEntity}s).\n     *\n     * @param type The type\n     * @return The normalized type\n     */\n    static String normalizeResponseWrapper(final String type) {\n        if (!getTypeParameters(type).isEmpty() && isAssignableTo(type, Types.GENERIC_ENTITY))\n            return getTypeParameters(type).get(0);\n        return type;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/ResultInterpreter.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.ClassComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MemberComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MemberParameterTag;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ResourceMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Response;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.Optional;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.JavaDocParameterResolver.*;\n\n/**\n * Interprets the analyzed project results to REST results.\n *\n * @author Sebastian Daschner\n */\npublic class ResultInterpreter {\n\n    private JavaTypeAnalyzer javaTypeAnalyzer;\n    private Resources resources;\n    private DynamicTypeAnalyzer dynamicTypeAnalyzer;\n    private StringParameterResolver stringParameterResolver;\n\n    /**\n     * Interprets the class results.\n     *\n     * @return All REST resources\n     */\n    public Resources interpret(final Set<ClassResult> classResults) {\n        resources = new Resources();\n        resources.setBasePath(PathNormalizer.getApplicationPath(classResults));\n\n        javaTypeAnalyzer = new JavaTypeAnalyzer(resources.getTypeRepresentations());\n        dynamicTypeAnalyzer = new DynamicTypeAnalyzer(resources.getTypeRepresentations());\n        stringParameterResolver = new StringParameterResolver(resources.getTypeRepresentations(), javaTypeAnalyzer);\n\n        classResults.stream().filter(c -> c.getResourcePath() != null).forEach(this::interpretClassResult);\n        resources.consolidateMultiplePaths();\n\n        return resources;\n    }\n\n    /**\n     * Interprets the class result.\n     *\n     * @param classResult The class result\n     */\n    private void interpretClassResult(final ClassResult classResult) {\n        classResult.getMethods().forEach(m -> interpretMethodResult(m, classResult));\n    }\n\n    /**\n     * Interprets the method result.\n     *\n     * @param methodResult The method result\n     * @param classResult  The result of the containing class\n     */\n    private void interpretMethodResult(final MethodResult methodResult, final ClassResult classResult) {\n        if (methodResult.getSubResource() != null) {\n            interpretClassResult(methodResult.getSubResource());\n            return;\n        }\n\n        // determine resource of the method\n        final String path = PathNormalizer.getPath(methodResult);\n\n        final ResourceMethod resourceMethod = interpretResourceMethod(methodResult, classResult);\n\n        resources.addMethod(path, resourceMethod);\n    }\n\n    /**\n     * Interprets the result of a resource method.\n     *\n     * @param methodResult The method result\n     * @param classResult  The result of the containing class\n     * @return The resource method which this method represents\n     */\n    private ResourceMethod interpretResourceMethod(final MethodResult methodResult, final ClassResult classResult) {\n        final MethodComment methodDoc = methodResult.getMethodDoc();\n\n        final String description = methodDoc != null ? methodDoc.getComment() : null;\n        final ResourceMethod resourceMethod = new ResourceMethod(methodResult.getHttpMethod(), description);\n        updateMethodParameters(resourceMethod.getMethodParameters(), classResult.getClassFields());\n        updateMethodParameters(resourceMethod.getMethodParameters(), methodResult.getMethodParameters());\n\n        addParameterDescriptions(resourceMethod.getMethodParameters(), methodDoc);\n        stringParameterResolver.replaceParametersTypes(resourceMethod.getMethodParameters());\n\n        if (methodResult.getRequestBodyType() != null) {\n            resourceMethod.setRequestBody(javaTypeAnalyzer.analyze(methodResult.getRequestBodyType()));\n            resourceMethod.setRequestBodyDescription(findRequestBodyDescription(methodDoc));\n        }\n\n        // add default status code due to JSR 339\n        addDefaultResponses(methodResult);\n\n        methodResult.getResponses().forEach(r -> interpretResponse(r, resourceMethod));\n\n        addResponseComments(methodResult, resourceMethod);\n\n        addMediaTypes(methodResult, classResult, resourceMethod);\n\n        if (methodResult.isDeprecated() || classResult.isDeprecated() || hasDeprecationTag(methodDoc))\n            resourceMethod.setDeprecated(true);\n\n        return resourceMethod;\n    }\n\n    /**\n     * Adds the comments for the individual status code to the corresponding Responses.\n     * The information is based on the {@code @response} javadoc tags.\n     */\n    private void addResponseComments(MethodResult methodResult, ResourceMethod resourceMethod) {\n        MethodComment methodDoc = methodResult.getMethodDoc();\n        if (methodDoc == null)\n            return;\n\n        methodDoc.getResponseComments()\n                .forEach((k, v) -> addResponseComment(k, v, resourceMethod));\n\n        ClassComment classDoc = methodDoc.getContainingClassComment();\n\n        // class-level response comments are added last (if absent) to keep hierarchy\n        if (classDoc != null)\n            classDoc.getResponseComments()\n                    .forEach((k, v) -> addResponseComment(k, v, resourceMethod));\n    }\n\n    private void addResponseComment(Integer status, String comment, ResourceMethod resourceMethod) {\n        resourceMethod.getResponses().putIfAbsent(status, new Response(null, comment));\n    }\n\n    private boolean hasDeprecationTag(MethodComment doc) {\n        if (doc == null)\n            return false;\n        return doc.isDeprecated() || hasClassDeprecationTag(doc.getContainingClassComment());\n    }\n\n    private boolean hasClassDeprecationTag(MemberComment doc) {\n        return doc != null && doc.isDeprecated();\n    }\n\n    private void addParameterDescriptions(final Set<MethodParameter> methodParameters, final MethodComment methodDoc) {\n        if (methodDoc == null)\n            return;\n\n        methodParameters.forEach(p -> {\n            final Optional<MemberParameterTag> tag = findParameterDoc(p, methodDoc);\n\n            final String description = tag.map(MemberParameterTag::getComment)\n                    .orElseGet(() -> findFieldDoc(p, methodDoc.getContainingClassComment())\n                            .map(MemberParameterTag::getComment).orElse(null));\n\n            p.setDescription(description);\n        });\n    }\n\n    private String findRequestBodyDescription(final MethodComment methodDoc) {\n        if (methodDoc == null)\n            return null;\n        return findRequestBodyDoc(methodDoc).map(MemberParameterTag::getComment).orElse(null);\n    }\n\n    /**\n     * Updates {@code parameters} to contain the {@code additional} parameters as well.\n     * Preexisting parameters with identical names are overridden.\n     */\n    private void updateMethodParameters(final Set<MethodParameter> parameters, final Set<MethodParameter> additional) {\n        additional.forEach(a -> {\n            // remove preexisting parameters with identical names\n            final Optional<MethodParameter> existingParameter = parameters.stream().filter(p -> p.getName().equals(a.getName())).findAny();\n            existingParameter.ifPresent(parameters::remove);\n            parameters.add(a);\n        });\n    }\n\n    private void addDefaultResponses(final MethodResult methodResult) {\n        if (methodResult.getResponses().isEmpty()) {\n            final HttpResponse httpResponse = new HttpResponse();\n            httpResponse.getStatuses().add(javax.ws.rs.core.Response.Status.NO_CONTENT.getStatusCode());\n            methodResult.getResponses().add(httpResponse);\n            return;\n        }\n\n        methodResult.getResponses().stream().filter(r -> r.getStatuses().isEmpty())\n                .forEach(r -> r.getStatuses().add(javax.ws.rs.core.Response.Status.OK.getStatusCode()));\n    }\n\n    private void interpretResponse(final HttpResponse httpResponse, final ResourceMethod method) {\n        method.getResponseMediaTypes().addAll(httpResponse.getContentTypes());\n        httpResponse.getStatuses().forEach(s -> {\n            Response response = httpResponse.getInlineEntities().stream().findAny()\n                    .map(JsonMapper::map).map(dynamicTypeAnalyzer::analyze).map(Response::new).orElse(null);\n\n            if (response == null) {\n                // no inline entities -> potential class type will be considered\n                response = httpResponse.getEntityTypes().isEmpty() ? new Response() :\n                        new Response(javaTypeAnalyzer.analyze(JavaUtils.determineMostSpecificType(httpResponse.getEntityTypes().toArray(new String[0]))));\n            }\n\n            response.getHeaders().addAll(httpResponse.getHeaders());\n\n            method.getResponses().put(s, response);\n        });\n    }\n\n    /**\n     * Adds the request and response media type information to the resource method.\n     *\n     * @param methodResult   The method result\n     * @param classResult    The class result\n     * @param resourceMethod The resource method\n     */\n    private void addMediaTypes(final MethodResult methodResult, final ClassResult classResult, final ResourceMethod resourceMethod) {\n        // accept media types -> inherit\n        resourceMethod.getRequestMediaTypes().addAll(methodResult.getRequestMediaTypes());\n        if (resourceMethod.getRequestMediaTypes().isEmpty()) {\n            resourceMethod.getRequestMediaTypes().addAll(classResult.getRequestMediaTypes());\n        }\n\n        // response media types -> use annotations if not yet present\n        if (resourceMethod.getResponseMediaTypes().isEmpty())\n            resourceMethod.getResponseMediaTypes().addAll(methodResult.getResponseMediaTypes());\n        // -> inherit\n        if (resourceMethod.getResponseMediaTypes().isEmpty()) {\n            resourceMethod.getResponseMediaTypes().addAll(classResult.getResponseMediaTypes());\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/StringParameterResolver.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Replaces all method parameter types which are not Strings, primitives, enums or collections of these with the String type.\n * JSR 339 requires the types to be serializable as String (in fact to have a String constructor or a {@code valueOf} method, respectively).\n * Therefore the types are assumed to be represented as String when exposed via REST.\n */\nclass StringParameterResolver {\n\n    private final Map<TypeIdentifier, TypeRepresentation> typeRepresentations;\n    private final JavaTypeAnalyzer javaTypeAnalyzer;\n\n    StringParameterResolver(final Map<TypeIdentifier, TypeRepresentation> typeRepresentations, final JavaTypeAnalyzer javaTypeAnalyzer) {\n        this.typeRepresentations = typeRepresentations;\n        this.javaTypeAnalyzer = javaTypeAnalyzer;\n    }\n\n    void replaceParametersTypes(final Set<MethodParameter> parameters) {\n        parameters.forEach(p -> {\n            if (isStringOrPrimitive(p.getType()))\n                return;\n\n            final TypeIdentifier identifier = javaTypeAnalyzer.analyze(p.getType().getType());\n            final TypeRepresentation typeRepresentation = typeRepresentations.get(identifier);\n\n            if (isEnum(typeRepresentation))\n                return;\n\n            if (isCollection(typeRepresentation)) {\n                final TypeIdentifier componentType = typeRepresentation.getComponentType();\n                if (isStringOrPrimitive(componentType) || isEnum(typeRepresentations.get(componentType)))\n                    return;\n\n                p.setType(javaTypeAnalyzer.analyze(\"Ljava/util/List<Ljava/lang/String;>;\"));\n                return;\n            }\n\n            p.setType(TypeIdentifier.ofType(Types.STRING));\n        });\n    }\n\n    private boolean isStringOrPrimitive(final TypeIdentifier componentType) {\n        return componentType.getType().equals(Types.STRING) || Types.PRIMITIVE_TYPES_ALL.contains(componentType.getType());\n    }\n\n    private boolean isEnum(final TypeRepresentation typeRepresentation) {\n        return typeRepresentation instanceof TypeRepresentation.EnumTypeRepresentation;\n    }\n\n    private boolean isCollection(final TypeRepresentation typeRepresentation) {\n        return typeRepresentation instanceof TypeRepresentation.CollectionTypeRepresentation;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/Backend.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.backend;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Project;\n\nimport java.util.Map;\n\n/**\n * Renders the analyzed JAX-RS resources into a String representation.\n *\n * @author Sebastian Daschner\n */\npublic interface Backend {\n\n    /**\n     * Renders the REST resources of the given project.\n     *\n     * @param project The project to render including all information and resources\n     * @return The data\n     */\n    byte[] render(Project project);\n\n    /**\n     * Returns a human readable name of the actual backend.\n     */\n    String getName();\n\n    /**\n     * Configures the backend.\n     */\n    default void configure(Map<String, String> config) {\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/ComparatorUtils.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\n\nimport java.util.Comparator;\nimport java.util.Map;\n\n/**\n * Common used functionality for creating comparators.\n *\n * @author Sebastian Daschner\n */\npublic final class ComparatorUtils {\n\n    private ComparatorUtils() {\n        throw new UnsupportedOperationException();\n    }\n\n    public static <T extends Comparable<? super T>> Comparator<Map.Entry<T, ?>> mapKeyComparator() {\n        return Comparator.comparing(Map.Entry::getKey);\n    }\n\n    public static Comparator<MethodParameter> parameterComparator() {\n        return Comparator.comparing(MethodParameter::getName);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/JsonRepresentationAppender.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.BOOLEAN;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.DOUBLE_TYPES;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.INTEGER_TYPES;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.PRIMITIVE_BOOLEAN;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.STRING;\nimport static java.util.Collections.singletonMap;\n\nimport java.io.StringReader;\nimport java.io.StringWriter;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport javax.json.JsonReader;\nimport javax.json.JsonWriter;\nimport javax.json.spi.JsonProvider;\nimport javax.json.stream.JsonGenerator;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentationVisitor;\n\n/**\n * Adds the JSON representation of type identifiers to String builders.\n *\n * @author Sebastian Daschner\n */\nclass JsonRepresentationAppender implements TypeRepresentationVisitor {\n\n    private final StringBuilder builder;\n    private final Map<TypeIdentifier, TypeRepresentation> representations;\n\n    private Set<TypeIdentifier> visitedTypes = new HashSet<>();\n\n    JsonRepresentationAppender(final StringBuilder builder, final Map<TypeIdentifier, TypeRepresentation> representations) {\n        this.builder = builder;\n        this.representations = representations;\n    }\n\n    @Override\n    public void visit(TypeRepresentation.ConcreteTypeRepresentation representation) {\n        if (representation.getProperties().isEmpty())\n            builder.append(toPrimitiveType(representation.getIdentifier()));\n        else {\n            builder.append('{');\n            visitedTypes.add(representation.getIdentifier());\n            representation.getProperties().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> {\n                builder.append('\"').append(e.getKey()).append(\"\\\":\");\n                final TypeRepresentation nestedRepresentation = representations.get(e.getValue());\n                if (nestedRepresentation == null)\n                    builder.append(toPrimitiveType(e.getValue()));\n                else if (visitedTypes.contains(e.getValue()))\n                    // prevent infinite loop from recursively nested types\n                    builder.append(\"{}\");\n                else\n                    nestedRepresentation.accept(this);\n                builder.append(',');\n            });\n            visitedTypes.remove(representation.getIdentifier());\n            builder.deleteCharAt(builder.length() - 1).append('}');\n        }\n    }\n\n    @Override\n    public void visitStart(TypeRepresentation.CollectionTypeRepresentation representation) {\n        builder.append('[');\n    }\n\n    @Override\n    public void visitEnd(TypeRepresentation.CollectionTypeRepresentation representation) {\n        builder.append(']');\n    }\n\n    @Override\n    public void visit(final TypeRepresentation.EnumTypeRepresentation representation) {\n        final String values = '\"' + representation.getEnumValues().stream().sorted()\n                .collect(Collectors.joining(\"|\")) + '\"';\n\n        builder.append(values.length() == 2 ? \"\\\"string\\\"\" : values);\n    }\n\n    private static String toPrimitiveType(final TypeIdentifier value) {\n        final String type = value.getType();\n        if (STRING.equals(type))\n            return \"\\\"string\\\"\";\n\n        if (BOOLEAN.equals(type) || PRIMITIVE_BOOLEAN.equals(type))\n            return \"false\";\n\n        if (INTEGER_TYPES.contains(type))\n            return \"0\";\n\n        if (DOUBLE_TYPES.contains(type))\n            return \"0.0\";\n\n        return \"{}\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/StringBackend.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\n\nimport javax.json.*;\nimport javax.json.spi.JsonProvider;\nimport javax.json.stream.JsonGenerator;\nimport java.io.StringReader;\nimport java.io.StringWriter;\nimport java.util.Map;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.regex.Pattern;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;\nimport static java.util.Collections.singletonMap;\nimport static java.util.Comparator.comparing;\n\n/**\n * A backend that is backed by Strings (plain text).\n *\n * @author Sebastian Daschner\n */\npublic abstract class StringBackend implements Backend {\n\n    public static final String INLINE_PRETTIFY = \"inlinePrettify\";\n    private static final String INLINE_PRETTIFY_DEFAULT = \"true\";\n    private static final Pattern CLEAR_COMPONENT_TYPE = Pattern.compile(\"[+\\\\-]\");\n\n    protected final Lock lock = new ReentrantLock();\n    protected StringBuilder builder;\n    protected Resources resources;\n    protected String projectName;\n    protected String projectVersion;\n    protected boolean prettify;\n\n    @Override\n    public void configure(final Map<String, String> config) {\n        prettify = Boolean.parseBoolean(config.getOrDefault(INLINE_PRETTIFY, INLINE_PRETTIFY_DEFAULT));\n    }\n\n    @Override\n    public byte[] render(final Project project) {\n        lock.lock();\n        try {\n            initRender(project);\n\n            final String output = renderInternal();\n\n            return serialize(output);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private void initRender(final Project project) {\n        // initialize fields\n        builder = new StringBuilder();\n        resources = project.getResources();\n        projectName = project.getName();\n        projectVersion = project.getVersion();\n    }\n\n    private String renderInternal() {\n        appendHeader();\n\n        resources.getResources().stream().sorted().forEach(this::appendResource);\n\n        return builder.toString();\n    }\n\n    private void appendHeader() {\n        appendFirstLine();\n        builder.append(projectVersion).append(\"\\n\\n\");\n    }\n\n    private void appendResource(final String resource) {\n        resources.getMethods(resource).stream()\n                .sorted(comparing(ResourceMethod::getMethod))\n                .forEach(resourceMethod -> {\n                    appendMethod(resources.getBasePath(), resource, resourceMethod);\n                    appendRequest(resourceMethod);\n                    appendResponse(resourceMethod);\n                    appendResourceEnd();\n                });\n    }\n\n    protected abstract void appendFirstLine();\n\n    protected abstract void appendMethod(String baseUri, String resource, ResourceMethod resourceMethod);\n\n    protected abstract void appendRequest(ResourceMethod resourceMethod);\n\n    protected abstract void appendResponse(ResourceMethod resourceMethod);\n\n    protected void appendResourceEnd() {\n    }\n\n    protected String doVisit(final TypeRepresentation typeRepresentation) {\n        final StringBuilder builder = new StringBuilder();\n        final TypeRepresentationVisitor appender = new JsonRepresentationAppender(builder,\n                resources.getTypeRepresentations());\n        typeRepresentation.accept(appender);\n        final String json = builder.toString();\n        return prettify ? format(json) : json;\n    }\n\n    protected String toReadableComponentType(TypeIdentifier componentType) {\n        final String type = componentType.getType();\n        return toReadableType(CLEAR_COMPONENT_TYPE.matcher(type).replaceAll(\"\"));\n    }\n\n    private static byte[] serialize(final String output) {\n        return output.getBytes();\n    }\n\n    private String format(final String json) {\n        final JsonProvider provider = JsonProvider.provider();\n        final StringWriter out = new StringWriter();\n        try (final JsonReader reader = provider.createReader(new StringReader(json));\n             final JsonWriter jsonWriter = provider.createWriterFactory(singletonMap(JsonGenerator.PRETTY_PRINTING, true))\n                     .createWriter(out)) {\n\n            // jsonWriter.write(reader.readValue()); // bug in RI, can switch to johnzon\n            final JsonStructure read = reader.read();\n            if (read.getValueType() == JsonValue.ValueType.OBJECT) {\n                jsonWriter.writeObject(JsonObject.class.cast(read));\n            } else if (read.getValueType() == JsonValue.ValueType.ARRAY) {\n                jsonWriter.writeArray(JsonArray.class.cast(read));\n            } else { // no reformatting\n                return json;\n            }\n            return out.toString().trim();\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/asciidoc/AsciiDocBackend.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.asciidoc;\n\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ResourceMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Response;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.parameterComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;\n\n/**\n * A backend implementation which produces an AsciiDoc representation of the JAX-RS project.\n *\n * @author Sebastian Daschner\n */\npublic class AsciiDocBackend extends StringBackend {\n\n    private static final String NAME = \"AsciiDoc\";\n    private static final String DOCUMENT_TITLE = \"= REST resources of \";\n    private static final String TYPE_WILDCARD = \"\\\\*/*\";\n\n    @Override\n    protected void appendMethod(final String baseUri, final String resource, final ResourceMethod resourceMethod) {\n        builder.append(\"== `\").append(resourceMethod.getMethod()).append(' ');\n        if (!StringUtils.isBlank(baseUri))\n            builder.append(baseUri).append('/');\n        builder.append(resource).append(\"`\\n\\n\");\n        if( !StringUtils.isBlank( resourceMethod.getDescription() ) )\n            builder.append( \"=== Description: \" ).append( resourceMethod.getDescription() ).append( \"\\n\\n\" );\n        if (resourceMethod.isDeprecated())\n            builder.append(\"CAUTION: deprecated\\n\\n\");\n    }\n\n    @Override\n    protected void appendRequest(final ResourceMethod resourceMethod) {\n        builder.append(\"=== Request\\n\");\n\n        if (resourceMethod.getRequestBody() != null) {\n            builder.append(\"*Content-Type*: `\");\n            builder.append(resourceMethod.getRequestMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getRequestMediaTypes()));\n            builder.append(\"` + \\n\");\n\n            builder.append(\"*Request Body*: (\").append(toTypeOrCollection(resourceMethod.getRequestBody())).append(\")\");\n            Optional.ofNullable(resources.getTypeRepresentations().get(resourceMethod.getRequestBody())).ifPresent(\n                    this::generateSample);\n            builder.append(\"\\n\");\n        } else {\n            builder.append(\"_No body_ + \\n\");\n        }\n\n        final Set<MethodParameter> parameters = resourceMethod.getMethodParameters();\n\n        appendParams(\"Path Param\", parameters, ParameterType.PATH);\n        appendParams(\"Query Param\", parameters, ParameterType.QUERY);\n        appendParams(\"Form Param\", parameters, ParameterType.FORM);\n        appendParams(\"Header Param\", parameters, ParameterType.HEADER);\n        appendParams(\"Cookie Param\", parameters, ParameterType.COOKIE);\n        appendParams(\"Matrix Param\", parameters, ParameterType.MATRIX);\n\n        builder.append('\\n');\n    }\n\n    private void appendParams(final String name, final Set<MethodParameter> parameters, final ParameterType parameterType) {\n        parameters.stream().filter(p -> p.getParameterType() == parameterType)\n                .sorted(parameterComparator()).forEach(p -> builder\n                .append('*')\n                .append(name)\n                .append(\"*: `\")\n                .append(p.getName())\n                .append(\"`, `\")\n                .append(toReadableType(p.getType().getType()))\n                // TODO add default value\n                .append(\"` + \\n\"));\n    }\n\n    @Override\n    protected void appendResponse(final ResourceMethod resourceMethod) {\n        builder.append(\"=== Response\\n\");\n\n        builder.append(\"*Content-Type*: `\");\n        builder.append(resourceMethod.getResponseMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getResponseMediaTypes()));\n        builder.append(\"`\\n\\n\");\n\n        resourceMethod.getResponses().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> {\n            builder.append(\"==== `\").append(e.getKey()).append(' ')\n                    .append(javax.ws.rs.core.Response.Status.fromStatusCode(e.getKey()).getReasonPhrase()).append(\"`\\n\");\n            final Response response = e.getValue();\n            response.getHeaders().forEach(h -> builder.append(\"*Header*: `\").append(h).append(\"` + \\n\"));\n\n            if (response.getResponseBody() != null) {\n                builder.append(\"*Response Body*: \").append('(').append(toTypeOrCollection(response.getResponseBody())).append(\")\");\n                Optional.ofNullable(resources.getTypeRepresentations().get(response.getResponseBody())).ifPresent(\n                        this::generateSample);\n                builder.append(\"\\n\");\n            }\n\n            builder.append('\\n');\n        });\n    }\n\n    private void generateSample(TypeRepresentation r) {\n        builder.append(\"\\n\\n[source,javascript]\\n----\\n\");\n        builder.append(doVisit(r));\n        builder.append(\"\\n----\\n\\n\");\n    }\n\n    private String toTypeOrCollection(final TypeIdentifier type) {\n        final TypeRepresentation representation = resources.getTypeRepresentations().get(type);\n        if (representation != null && !representation.getComponentType().equals(type) && !type.getType().equals(Types.JSON)) {\n            return \"Collection of `\" + toReadableComponentType(representation.getComponentType()) + '`';\n        }\n        return '`' + toReadableType(type.getType()) + '`';\n    }\n\n    private static String toString(final Set<String> set) {\n        return set.stream().sorted().map(Object::toString).collect(Collectors.joining(\", \"));\n    }\n\n    @Override\n    public String getName() {\n        return NAME;\n    }\n\n    @Override\n    protected void appendFirstLine() {\n        builder.append(DOCUMENT_TITLE).append(projectName).append(\"\\n\");\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/markdown/MarkdownBackend.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.markdown;\n\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ResourceMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Response;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.parameterComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;\n\n\n/**\n * A backend implementation which produces an Markdown representation of the JAX-RS project.\n *\n * @author Sven Ehnert\n */\npublic class MarkdownBackend extends StringBackend {\n\n    private static final String NAME = \"Markdown\";\n    private static final String DOCUMENT_TITLE = \"# REST resources of \";\n    private static final String TYPE_WILDCARD = \"\\\\*/*\";\n\n    @Override\n    protected void appendMethod(final String baseUri, final String resource, final ResourceMethod resourceMethod) {\n        builder.append(\"## `\").append(resourceMethod.getMethod()).append(' ');\n        if (!StringUtils.isBlank(baseUri))\n            builder.append(baseUri).append('/');\n        builder.append(resource).append(\"`\\n\\n\");\n        if( !StringUtils.isBlank( resourceMethod.getDescription() ) )\n            builder.append( \"### Description: \" ).append( resourceMethod.getDescription() ).append( \"\\n\\n\" );\n        if (resourceMethod.isDeprecated())\n            builder.append(\"CAUTION: deprecated\\n\\n\");\n    }\n\n    @Override\n    protected void appendRequest(final ResourceMethod resourceMethod) {\n        builder.append(\"### Request\\n\");\n\n        if (resourceMethod.getRequestBody() != null) {\n            builder.append(\"*Content-Type*: `\");\n            builder.append(resourceMethod.getRequestMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getRequestMediaTypes()));\n            builder.append(\"` + \\n\");\n\n            builder.append(\"*Request Body*: (\").append(toTypeOrCollection(resourceMethod.getRequestBody())).append(\")\");\n            Optional.ofNullable(resources.getTypeRepresentations().get(resourceMethod.getRequestBody())).ifPresent(\n                    this::generateSample);\n            builder.append(\"\\n\");\n        } else {\n            builder.append(\"_No body_ + \\n\");\n        }\n\n        final Set<MethodParameter> parameters = resourceMethod.getMethodParameters();\n\n        appendParams(\"Path Param\", parameters, ParameterType.PATH);\n        appendParams(\"Query Param\", parameters, ParameterType.QUERY);\n        appendParams(\"Form Param\", parameters, ParameterType.FORM);\n        appendParams(\"Header Param\", parameters, ParameterType.HEADER);\n        appendParams(\"Cookie Param\", parameters, ParameterType.COOKIE);\n        appendParams(\"Matrix Param\", parameters, ParameterType.MATRIX);\n\n        builder.append('\\n');\n    }\n\n    private void appendParams(final String name, final Set<MethodParameter> parameters, final ParameterType parameterType) {\n        parameters.stream().filter(p -> p.getParameterType() == parameterType)\n                .sorted(parameterComparator()).forEach(p -> builder\n                .append('*')\n                .append(name)\n                .append(\"*: `\")\n                .append(p.getName())\n                .append(\"`, `\")\n                .append(toReadableType(p.getType().getType()))\n                // TODO add default value\n                .append(\"` + \\n\"));\n    }\n\n    @Override\n    protected void appendResponse(final ResourceMethod resourceMethod) {\n        builder.append(\"### Response\\n\");\n\n        builder.append(\"*Content-Type*: `\");\n        builder.append(resourceMethod.getResponseMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getResponseMediaTypes()));\n        builder.append(\"`\\n\\n\");\n\n        resourceMethod.getResponses().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> {\n            builder.append(\"#### `\").append(e.getKey()).append(' ')\n                    .append(javax.ws.rs.core.Response.Status.fromStatusCode(e.getKey()).getReasonPhrase()).append(\"`\\n\");\n            final Response response = e.getValue();\n            response.getHeaders().forEach(h -> builder.append(\"*Header*: `\").append(h).append(\"` + \\n\"));\n\n            if (response.getResponseBody() != null) {\n                builder.append(\"*Response Body*: \").append('(').append(toTypeOrCollection(response.getResponseBody())).append(\")\");\n                Optional.ofNullable(resources.getTypeRepresentations().get(response.getResponseBody())).ifPresent(\n                        this::generateSample);\n                builder.append(\"\\n\");\n            }\n\n            builder.append('\\n');\n        });\n    }\n\n    private void generateSample(TypeRepresentation r) {\n        builder.append(\"\\n\\n```javascript\\n\");\n        builder.append(doVisit(r));\n        builder.append(\"\\n```\\n\\n\");\n    }\n\n    private String toTypeOrCollection(final TypeIdentifier type) {\n        final TypeRepresentation representation = resources.getTypeRepresentations().get(type);\n        if (representation != null && !representation.getComponentType().equals(type) && !type.getType().equals(Types.JSON)) {\n            return \"Collection of `\" + toReadableComponentType(representation.getComponentType()) + '`';\n        }\n        return '`' + toReadableType(type.getType()) + '`';\n    }\n\n    private static String toString(final Set<String> set) {\n        return set.stream().sorted().map(Object::toString).collect(Collectors.joining(\", \"));\n    }\n\n    @Override\n    public String getName() {\n        return NAME;\n    }\n\n    @Override\n    protected void appendFirstLine() {\n        builder.append(DOCUMENT_TITLE).append(projectName).append(\"\\n\\n\");\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/plaintext/PlainTextBackend.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.backend.plaintext;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.parameterComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType;\n\n/**\n * A thread-safe backend which produces a plain text representation of the JAX-RS analysis.\n *\n * @author Sebastian Daschner\n */\npublic class PlainTextBackend extends StringBackend {\n\n    private static final String NAME = \"PlainText\";\n    private static final String REST_HEADER = \"REST resources of \";\n    private static final String TYPE_WILDCARD = \"*/*\";\n\n    @Override\n    protected void appendMethod(final String baseUri, final String resource, final ResourceMethod resourceMethod) {\n        builder.append(resourceMethod.getMethod()).append(' ');\n        if (!StringUtils.isBlank(baseUri))\n            builder.append(baseUri).append('/');\n        builder.append(resource).append(\":\\n\");\n        if (!StringUtils.isBlank(resourceMethod.getDescription()))\n            builder.append(\"Description: \").append(resourceMethod.getDescription()).append(\"\\n\");\n        if (resourceMethod.isDeprecated())\n            builder.append(\" Deprecated\\n\");\n    }\n\n    @Override\n    protected void appendRequest(final ResourceMethod resourceMethod) {\n        builder.append(\" Request:\\n\");\n\n        if (resourceMethod.getRequestBody() != null) {\n            builder.append(\"  Content-Type: \");\n            builder.append(resourceMethod.getRequestMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getRequestMediaTypes()));\n            builder.append('\\n');\n\n            builder.append(\"  Request Body: \").append(toTypeOrCollection(resourceMethod.getRequestBody())).append('\\n');\n            Optional.ofNullable(resources.getTypeRepresentations().get(resourceMethod.getRequestBody())).ifPresent(r -> {\n                if (!prettify)\n                    builder.append(\"   \");\n                builder.append(doVisit(r));\n                builder.append('\\n');\n            });\n        } else {\n            builder.append(\"  No body\\n\");\n        }\n\n        final Set<MethodParameter> parameters = resourceMethod.getMethodParameters();\n\n        appendParams(\"  Path Param: \", parameters, ParameterType.PATH);\n        appendParams(\"  Query Param: \", parameters, ParameterType.QUERY);\n        appendParams(\"  Form Param: \", parameters, ParameterType.FORM);\n        appendParams(\"  Header Param: \", parameters, ParameterType.HEADER);\n        appendParams(\"  Cookie Param: \", parameters, ParameterType.COOKIE);\n        appendParams(\"  Matrix Param: \", parameters, ParameterType.MATRIX);\n\n        builder.append('\\n');\n    }\n\n    private void appendParams(final String name, final Set<MethodParameter> parameters, final ParameterType parameterType) {\n        parameters.stream().filter(p -> p.getParameterType() == parameterType)\n                .sorted(parameterComparator()).forEach(p -> builder\n                .append(name)\n                .append(p.getName())\n                .append(\", \")\n                .append(toReadableType(p.getType().getType()))\n                // TODO add default value\n                .append('\\n'));\n    }\n\n    @Override\n    protected void appendResponse(final ResourceMethod resourceMethod) {\n        builder.append(\" Response:\\n\");\n\n        builder.append(\"  Content-Type: \");\n        builder.append(resourceMethod.getResponseMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getResponseMediaTypes()));\n        builder.append('\\n');\n\n        resourceMethod.getResponses().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> {\n            builder.append(\"  Status Codes: \").append(e.getKey()).append('\\n');\n            final Response response = e.getValue();\n            if (!response.getHeaders().isEmpty()) {\n                builder.append(\"   Header: \").append(response.getHeaders().stream().sorted().collect(Collectors.joining(\", \")));\n                builder.append('\\n');\n            }\n            if (response.getResponseBody() != null) {\n                builder.append(\"   Response Body: \").append(toTypeOrCollection(response.getResponseBody())).append('\\n');\n                Optional.ofNullable(resources.getTypeRepresentations().get(response.getResponseBody())).ifPresent(r -> {\n                    if (!prettify)\n                        builder.append(\"    \");\n                    builder.append(doVisit(r));\n                    builder.append('\\n');\n                });\n            }\n\n            builder.append('\\n');\n        });\n    }\n\n    @Override\n    protected void appendResourceEnd() {\n        builder.append(\"\\n\");\n    }\n\n    private String toTypeOrCollection(final TypeIdentifier type) {\n        final TypeRepresentation representation = resources.getTypeRepresentations().get(type);\n        if (representation != null && !representation.getComponentType().equals(type) && !type.getType().equals(Types.JSON)) {\n            return \"Collection of \" + toReadableComponentType(representation.getComponentType());\n        }\n        return toReadableType(type.getType());\n    }\n\n    private static String toString(final Set<String> set) {\n        return set.stream().sorted().map(Object::toString).collect(Collectors.joining(\", \"));\n    }\n\n    @Override\n    public String getName() {\n        return NAME;\n    }\n\n    @Override\n    protected void appendFirstLine() {\n        builder.append(REST_HEADER).append(projectName).append(\":\\n\");\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/DefinitionNameBuilder.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\n\nimport javax.json.JsonObject;\nimport java.util.Map;\n\nclass DefinitionNameBuilder {\n\n    String buildDefinitionName(final String typeName, Map<String, Pair<String, JsonObject>> jsonDefinitions) {\n        String definition = buildDefinitionName(typeName);\n\n        if (isOnlyType(typeName, definition, jsonDefinitions))\n            return definition;\n\n        // TODO can be problematic, see issue #155\n        if (!definition.matches(\"_\\\\d+$\"))\n            return definition + \"_2\";\n\n        final int separatorIndex = definition.lastIndexOf('_');\n        final int index = Integer.parseInt(definition.substring(separatorIndex + 1));\n        return definition.substring(0, separatorIndex + 1) + (index + 1);\n    }\n\n    private String buildDefinitionName(String typeName) {\n        if (isDynamicType(typeName))\n            return buildDynamicName(typeName);\n        return buildJavaTypeName(typeName);\n    }\n\n    private boolean isDynamicType(String typeName) {\n        return typeName.startsWith(TypeIdentifier.DYNAMIC_TYPE_PREFIX);\n    }\n\n    private String buildDynamicName(String typeName) {\n        return \"JsonObject\" + extractDynamicSuffix(typeName);\n    }\n\n    private String extractDynamicSuffix(String typeName) {\n        String id = typeName.substring(TypeIdentifier.DYNAMIC_TYPE_PREFIX.length());\n        return \"1\".equals(id) ? \"\" : \"_\" + id;\n    }\n\n    private String buildJavaTypeName(String typeName) {\n        return typeName.substring(typeName.lastIndexOf('/') + 1, typeName.length() - 1);\n    }\n\n    private boolean isOnlyType(String typeName, String definition, Map<String, Pair<String, JsonObject>> jsonDefinitions) {\n        final Pair<String, JsonObject> containedEntry = jsonDefinitions.get(definition);\n        return containedEntry == null || containedEntry.getLeft() != null && containedEntry.getLeft().equals(typeName);\n    }\n\n}"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SchemaBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentationVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.json.JsonObject;\nimport javax.json.JsonObjectBuilder;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\n/**\n * Creates Swagger schema type definitions.\n *\n * @author Sebastian Daschner\n */\nclass SchemaBuilder {\n\n    /**\n     * The fully-qualified class name together with the JSON definitions identified by the definition names.\n     */\n    private final Map<String, Pair<String, JsonObject>> jsonDefinitions = new HashMap<>();\n    private final DefinitionNameBuilder definitionNameBuilder = new DefinitionNameBuilder();\n\n    /**\n     * All known representation defined in the REST resources\n     */\n    private final Map<TypeIdentifier, TypeRepresentation> typeRepresentations;\n\n    SchemaBuilder(final Map<TypeIdentifier, TypeRepresentation> typeRepresentations) {\n        this.typeRepresentations = typeRepresentations;\n    }\n\n    /**\n     * Creates the schema object builder for the identifier.\n     * The actual definitions are retrieved via {@link SchemaBuilder#getDefinitions} after all types have been declared.\n     *\n     * @param identifier The identifier\n     * @return The schema JSON object builder with the needed properties\n     */\n    JsonObjectBuilder build(final TypeIdentifier identifier) {\n        final SwaggerType type = toSwaggerType(identifier.getType());\n        switch (type) {\n            case BOOLEAN:\n            case INTEGER:\n            case NUMBER:\n            case NULL:\n            case STRING:\n                final JsonObjectBuilder builder = Json.createObjectBuilder();\n                addPrimitive(builder, type);\n                return builder;\n        }\n\n        final JsonObjectBuilder builder = Json.createObjectBuilder();\n\n        final TypeRepresentationVisitor visitor = new TypeRepresentationVisitor() {\n\n            private boolean inCollection = false;\n\n            @Override\n            public void visit(final TypeRepresentation.ConcreteTypeRepresentation representation) {\n                final JsonObjectBuilder nestedBuilder = inCollection ? Json.createObjectBuilder() : builder;\n                add(nestedBuilder, representation);\n\n                if (inCollection) {\n                    builder.add(\"items\", nestedBuilder.build());\n                }\n            }\n\n            @Override\n            public void visitStart(final TypeRepresentation.CollectionTypeRepresentation representation) {\n                builder.add(\"type\", \"array\");\n                inCollection = true;\n            }\n\n            @Override\n            public void visitEnd(final TypeRepresentation.CollectionTypeRepresentation representation) {\n                builder.add(\"type\", \"array\");\n                inCollection = true;\n            }\n\n            @Override\n            public void visit(final TypeRepresentation.EnumTypeRepresentation representation) {\n                builder.add(\"type\", \"string\");\n                if (!representation.getEnumValues().isEmpty()) {\n                    final JsonArrayBuilder array = representation.getEnumValues().stream().sorted().collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add);\n                    if (inCollection) {\n                        builder.add(\"items\", Json.createObjectBuilder().add(\"type\", \"string\").add(\"enum\", array).build());\n                    } else {\n                        builder.add(\"enum\", array);\n                    }\n\n                }\n            }\n\n        };\n\n        final TypeRepresentation representation = typeRepresentations.get(identifier);\n        if (representation == null)\n            builder.add(\"type\", \"object\");\n        else\n            representation.accept(visitor);\n        return builder;\n    }\n\n    /**\n     * Returns the stored schema definitions. This has to be called after all calls of {@link SchemaBuilder#build(TypeIdentifier)}.\n     *\n     * @return The schema JSON definitions\n     */\n    JsonObject getDefinitions() {\n        final JsonObjectBuilder builder = Json.createObjectBuilder();\n        jsonDefinitions.entrySet().stream().sorted(mapKeyComparator()).forEach(e -> builder.add(e.getKey(), e.getValue().getRight()));\n        return builder.build();\n    }\n\n    private void add(final JsonObjectBuilder builder, final TypeRepresentation.ConcreteTypeRepresentation representation) {\n        final SwaggerType type = toSwaggerType(representation.getIdentifier().getType());\n        switch (type) {\n            case BOOLEAN:\n            case INTEGER:\n            case NUMBER:\n            case NULL:\n            case STRING:\n                addPrimitive(builder, type);\n                return;\n        }\n\n        addObject(builder, representation.getIdentifier(), representation.getProperties());\n    }\n\n    private void addObject(final JsonObjectBuilder builder, final TypeIdentifier identifier, final Map<String, TypeIdentifier> properties) {\n        final String definition = definitionNameBuilder.buildDefinitionName(identifier.getName(), jsonDefinitions);\n\n        if (jsonDefinitions.containsKey(definition)) {\n            builder.add(\"$ref\", \"#/definitions/\" + definition);\n            return;\n        }\n\n        // reserve definition\n        jsonDefinitions.put(definition, Pair.of(identifier.getName(), Json.createObjectBuilder().build()));\n\n        final JsonObjectBuilder nestedBuilder = Json.createObjectBuilder();\n\n        properties.entrySet().stream().sorted(mapKeyComparator()).forEach(e -> nestedBuilder.add(e.getKey(), build(e.getValue())));\n        jsonDefinitions.put(definition, Pair.of(identifier.getName(), Json.createObjectBuilder().add(\"properties\", nestedBuilder).build()));\n\n        builder.add(\"$ref\", \"#/definitions/\" + definition);\n    }\n\n    private void addPrimitive(final JsonObjectBuilder builder, final SwaggerType type) {\n        builder.add(\"type\", type.toString());\n    }\n\n    /**\n     * Converts the given Java type to the Swagger JSON type.\n     *\n     * @param type The Java type definition\n     * @return The Swagger type\n     */\n    private static SwaggerType toSwaggerType(final String type) {\n        if (INTEGER_TYPES.contains(type))\n            return SwaggerType.INTEGER;\n\n        if (DOUBLE_TYPES.contains(type))\n            return SwaggerType.NUMBER;\n\n        if (BOOLEAN.equals(type) || PRIMITIVE_BOOLEAN.equals(type))\n            return SwaggerType.BOOLEAN;\n\n        if (STRING.equals(type))\n            return SwaggerType.STRING;\n\n        return SwaggerType.OBJECT;\n    }\n\n    /**\n     * Represents the different Swagger types.\n     *\n     * @author Sebastian Daschner\n     */\n    private enum SwaggerType {\n\n        ARRAY, BOOLEAN, INTEGER, NULL, NUMBER, OBJECT, STRING;\n\n        @Override\n        public String toString() {\n            return super.toString().toLowerCase();\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SwaggerBackend.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport javax.json.*;\nimport javax.json.stream.JsonGenerator;\nimport javax.ws.rs.core.Response;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.Collectors;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.parameterComparator;\nimport static java.util.Collections.singletonMap;\nimport static java.util.Comparator.comparing;\n\n/**\n * A backend which produces a Swagger JSON representation of the resources.\n *\n * @author Sebastian Daschner\n */\npublic class SwaggerBackend implements Backend {\n\n    private static final String NAME = \"Swagger\";\n    private static final String SWAGGER_VERSION = \"2.0\";\n\n    private final Lock lock = new ReentrantLock();\n    private final SwaggerOptions options = new SwaggerOptions();\n\n    private Resources resources;\n    private JsonObjectBuilder builder;\n    private SchemaBuilder schemaBuilder;\n    private String projectName;\n    private String projectVersion;\n\n    @Override\n    public void configure(final Map<String, String> config) {\n        options.configure(config);\n    }\n\n    @Override\n    public byte[] render(final Project project) {\n        lock.lock();\n        try {\n            // initialize fields\n            builder = Json.createObjectBuilder();\n            resources = project.getResources();\n            projectName = project.getName();\n            projectVersion = project.getVersion();\n            schemaBuilder = new SchemaBuilder(resources.getTypeRepresentations());\n\n            final JsonObject output = modifyJson(renderInternal());\n\n            return serialize(output);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private JsonObject modifyJson(final JsonObject json) {\n        if (options.getJsonPatch() == null)\n            return json;\n        return options.getJsonPatch().apply(json);\n    }\n\n    private JsonObject renderInternal() {\n        appendHeader();\n        appendPaths();\n        appendDefinitions();\n\n        return builder.build();\n    }\n\n    private void appendHeader() {\n        renderHeader();\n        renderTags();\n    }\n\n    private void renderHeader() {\n        builder.add(\"swagger\", SWAGGER_VERSION).add(\"info\", Json.createObjectBuilder()\n                .add(\"version\", projectVersion).add(\"title\", projectName))\n                .add(\"host\", options.getDomain() == null ? \"\" : options.getDomain()).add(\"basePath\", (options.getDomain() != null && !\"\".equals(options.getDomain().trim()) ? '/' : '/' + projectName + '/') + resources.getBasePath())\n                .add(\"schemes\", options.getSchemes().stream().map(Enum::name).map(String::toLowerCase).sorted()\n                        .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add).build());\n    }\n\n    private void renderTags() {\n        if (options.isRenderTags()) {\n            final JsonArrayBuilder tags = Json.createArrayBuilder();\n            resources.getResources().stream()\n                    .map(this::extractTag).filter(Objects::nonNull)\n                    .distinct().sorted()\n                    .map(tag -> Json.createObjectBuilder().add(\"name\", tag))\n                    .forEach(tags::add);\n            builder.add(\"tags\", tags);\n        }\n    }\n\n    private String extractTag(final String s) {\n        final int offset = options.getTagsPathOffset();\n        final String[] parts = s.split(\"/\");\n\n        if (parts.length > offset && !parts[offset].contains(\"{\")) {\n            return parts[offset];\n        }\n        return null;\n    }\n\n    private void appendPaths() {\n        final JsonObjectBuilder paths = Json.createObjectBuilder();\n        resources.getResources().stream().sorted().forEach(s -> paths.add('/' + s, buildPathDefinition(s)));\n        builder.add(\"paths\", paths);\n    }\n\n    private JsonObjectBuilder buildPathDefinition(final String s) {\n        final JsonObjectBuilder methods = Json.createObjectBuilder();\n        consolidateMultipleMethodsForSamePath(s)\n                .values().stream()\n                .sorted(comparing(ResourceMethod::getMethod))\n                .forEach(m ->\n                        methods.add(m.getMethod().toString().toLowerCase(), buildForMethod(m, s)));\n        return methods;\n    }\n\n    private Map<String, ResourceMethod> consolidateMultipleMethodsForSamePath(String s) {\n        return resources.getMethods(s).stream().collect(\n                Collectors.groupingBy(m->m.getMethod().toString().toLowerCase(),\n                        Collectors.reducing(new ResourceMethod(), ResourceMethod::combine))\n        );\n    }\n\n    private JsonObjectBuilder buildForMethod(final ResourceMethod method, final String s) {\n        final JsonArrayBuilder consumes = Json.createArrayBuilder();\n        method.getRequestMediaTypes().stream().sorted().forEach(consumes::add);\n\n        final JsonArrayBuilder produces = Json.createArrayBuilder();\n        method.getResponseMediaTypes().stream().sorted().forEach(produces::add);\n\n        final JsonObjectBuilder builder = Json.createObjectBuilder();\n\n        if (method.getDescription() != null)\n            builder.add(\"description\", method.getDescription());\n\n        builder.add(\"consumes\", consumes).add(\"produces\", produces)\n                .add(\"parameters\", buildParameters(method)).add(\"responses\", buildResponses(method));\n\n        if (method.isDeprecated())\n            builder.add(\"deprecated\", true);\n\n        if (options.isRenderTags())\n            Optional.ofNullable(extractTag(s)).ifPresent(t -> builder.add(\"tags\", Json.createArrayBuilder().add(t)));\n\n        return builder;\n    }\n\n    private JsonArrayBuilder buildParameters(final ResourceMethod method) {\n        final Set<MethodParameter> parameters = method.getMethodParameters();\n        final JsonArrayBuilder parameterBuilder = Json.createArrayBuilder();\n\n        buildParameters(parameters, ParameterType.PATH, parameterBuilder);\n        buildParameters(parameters, ParameterType.HEADER, parameterBuilder);\n        buildParameters(parameters, ParameterType.QUERY, parameterBuilder);\n        buildParameters(parameters, ParameterType.FORM, parameterBuilder);\n\n        if (method.getRequestBody() != null) {\n            final JsonObjectBuilder requestBuilder = Json.createObjectBuilder()\n                    .add(\"name\", \"body\")\n                    .add(\"in\", \"body\")\n                    .add(\"required\", true)\n                    .add(\"schema\", schemaBuilder.build(method.getRequestBody()));\n            if (!StringUtils.isBlank(method.getRequestBodyDescription()))\n                requestBuilder.add(\"description\", method.getRequestBodyDescription());\n            parameterBuilder.add(requestBuilder);\n        }\n        return parameterBuilder;\n    }\n\n    private void buildParameters(final Set<MethodParameter> parameters, final ParameterType parameterType, final JsonArrayBuilder builder) {\n        parameters.stream().filter(p -> p.getParameterType() == parameterType)\n                .sorted(parameterComparator())\n                .forEach(e -> {\n                    final String swaggerParameterType = getSwaggerParameterType(parameterType);\n                    if (swaggerParameterType != null) {\n                        final JsonObjectBuilder paramBuilder = schemaBuilder.build(e.getType())\n                                .add(\"name\", e.getName())\n                                .add(\"in\", swaggerParameterType)\n                                .add(\"required\", e.getDefaultValue() == null);\n                        if (!StringUtils.isBlank(e.getDescription())) {\n                            paramBuilder.add(\"description\", e.getDescription());\n                        }\n                        if (!StringUtils.isBlank(e.getDefaultValue())) {\n                            paramBuilder.add(\"default\", e.getDefaultValue());\n                        }\n                        builder.add(paramBuilder);\n                    }\n                });\n    }\n\n    private JsonObjectBuilder buildResponses(final ResourceMethod method) {\n        final JsonObjectBuilder responses = Json.createObjectBuilder();\n\n        method.getResponses().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> {\n            final JsonObjectBuilder headers = Json.createObjectBuilder();\n            e.getValue().getHeaders().stream().sorted().forEach(h -> headers.add(h, Json.createObjectBuilder().add(\"type\", \"string\")));\n\n            final JsonObjectBuilder response = Json.createObjectBuilder()\n                    .add(\"description\", e.getValue().getDescription() != null ? e.getValue().getDescription() : Optional.ofNullable(Response.Status.fromStatusCode(e.getKey())).map(Response.Status::getReasonPhrase).orElse(\"\"))\n                    .add(\"headers\", headers);\n\n            if (e.getValue().getResponseBody() != null) {\n                final JsonObject schema = schemaBuilder.build(e.getValue().getResponseBody()).build();\n                if (!schema.isEmpty())\n                    response.add(\"schema\", schema);\n            }\n\n            responses.add(e.getKey().toString(), response);\n        });\n\n        return responses;\n    }\n\n    private void appendDefinitions() {\n        builder.add(\"definitions\", schemaBuilder.getDefinitions());\n    }\n\n\n    @Override\n    public String getName() {\n        return NAME;\n    }\n\n    private static String getSwaggerParameterType(final ParameterType parameterType) {\n        switch (parameterType) {\n            case QUERY:\n                return \"query\";\n            case PATH:\n                return \"path\";\n            case HEADER:\n                return \"header\";\n            case FORM:\n                return \"formData\";\n            default:\n                // TODO handle others (possible w/ Swagger?)\n                return null;\n        }\n    }\n\n    private static byte[] serialize(final JsonObject jsonObject) {\n        try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {\n            final Map<String, ?> config = singletonMap(JsonGenerator.PRETTY_PRINTING, true);\n            final JsonWriter jsonWriter = Json.createWriterFactory(config).createWriter(output);\n            jsonWriter.write(jsonObject);\n            jsonWriter.close();\n\n            return output.toByteArray();\n        } catch (IOException e) {\n            throw new RuntimeException(\"Could not write Swagger output\", e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SwaggerOptions.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\n\nimport javax.json.Json;\nimport javax.json.JsonArray;\nimport javax.json.JsonPatch;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.EnumSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Stream;\n\n/**\n * The Swagger backend specific configuration properties.\n *\n * @author Sebastian Daschner\n */\npublic class SwaggerOptions {\n\n    public static final String DOMAIN = \"domain\";\n    public static final String SWAGGER_SCHEMES = \"swaggerSchemes\";\n    public static final String RENDER_SWAGGER_TAGS = \"renderSwaggerTags\";\n    public static final String SWAGGER_TAGS_PATH_OFFSET = \"swaggerTagsPathOffset\";\n    public static final String JSON_PATCH = \"jsonPatch\";\n\n    private static final String DEFAULT_DOMAIN = \"\";\n    private static final Set<SwaggerScheme> DEFAULT_SCHEMES = EnumSet.of(SwaggerScheme.HTTP);\n    private static final boolean DEFAULT_RENDER_TAGS = false;\n    private static final int DEFAULT_TAGS_PATH_OFFSET = 0;\n\n    /**\n     * The deployed domain of the project.\n     */\n    private String domain = DEFAULT_DOMAIN;\n\n    /**\n     * The transfer protocol (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swaggerSchemes) of the project.\n     */\n    private Set<SwaggerScheme> schemes = DEFAULT_SCHEMES;\n\n    /**\n     * Flag if Swagger tags (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#tagObject)\n     * &mdash; generated from the paths &mdash; should be rendered.\n     */\n    private boolean renderTags = DEFAULT_RENDER_TAGS;\n\n    /**\n     * The path offset of the Swagger tags.\n     */\n    private int tagsPathOffset = DEFAULT_TAGS_PATH_OFFSET;\n\n    /**\n     * The optional JSON patch (RFC 6902) that can modify the Swagger JSON output.\n     */\n    private JsonPatch jsonPatch;\n\n    String getDomain() {\n        return domain;\n    }\n\n    Set<SwaggerScheme> getSchemes() {\n        return schemes;\n    }\n\n    boolean isRenderTags() {\n        return renderTags;\n    }\n\n    int getTagsPathOffset() {\n        return tagsPathOffset;\n    }\n\n    JsonPatch getJsonPatch() {\n        return jsonPatch;\n    }\n\n    void configure(final Map<String, String> config) {\n        if (config.containsKey(SWAGGER_TAGS_PATH_OFFSET)) {\n            int swaggerTagsPathOffset = Integer.parseInt(config.get(SWAGGER_TAGS_PATH_OFFSET));\n\n            if (swaggerTagsPathOffset < 0) {\n                System.err.println(\"Please provide positive integer number for option --swaggerTagsPathOffset\\n\");\n                throw new IllegalArgumentException(\"Please provide positive integer number for option --swaggerTagsPathOffset\");\n            }\n\n            tagsPathOffset = swaggerTagsPathOffset;\n        }\n\n        if (config.containsKey(DOMAIN)) {\n            domain = config.get(DOMAIN);\n        }\n\n        if (config.containsKey(SWAGGER_SCHEMES)) {\n            schemes = extractSwaggerSchemes(config.get(SWAGGER_SCHEMES));\n        }\n\n        if (config.containsKey(RENDER_SWAGGER_TAGS)) {\n            renderTags = Boolean.parseBoolean(config.get(RENDER_SWAGGER_TAGS));\n        }\n\n        if (config.containsKey(JSON_PATCH)) {\n            jsonPatch = readPatch(config.get(JSON_PATCH));\n        }\n    }\n\n    private Set<SwaggerScheme> extractSwaggerSchemes(final String schemes) {\n        return Stream.of(schemes.split(\",\"))\n                .map(this::extractSwaggerScheme)\n                .collect(() -> EnumSet.noneOf(SwaggerScheme.class), Set::add, Set::addAll);\n    }\n\n    private SwaggerScheme extractSwaggerScheme(final String scheme) {\n        switch (scheme.toLowerCase()) {\n            case \"http\":\n                return SwaggerScheme.HTTP;\n            case \"https\":\n                return SwaggerScheme.HTTPS;\n            case \"ws\":\n                return SwaggerScheme.WS;\n            case \"wss\":\n                return SwaggerScheme.WSS;\n            default:\n                throw new IllegalArgumentException(\"Unknown swagger scheme \" + scheme);\n        }\n    }\n\n    private static JsonPatch readPatch(final String patchFile) {\n        try {\n            final JsonArray patchArray = Json.createReader(Files.newBufferedReader(Paths.get(patchFile))).readArray();\n            return Json.createPatchBuilder(patchArray).build();\n        } catch (Exception e) {\n            LogProvider.error(\"Could not read JSON patch from the specified location, reason: \" + e.getMessage());\n            LogProvider.error(\"Patch won't be applied\");\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SwaggerScheme.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\n/**\n * The Swagger transfer protocols.\n *\n * @author Sebastian Daschner\n */\nenum SwaggerScheme {\n\n    HTTP, HTTPS, WS, WSS\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/JavaUtils.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.signature.SignatureReader;\nimport org.objectweb.asm.util.TraceSignatureVisitor;\n\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.AnnotatedElement;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.TypeVariable;\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\nimport static java.util.Collections.emptyList;\nimport static java.util.Collections.emptyMap;\n\n/**\n * Contains Java reflection utility functionality.\n *\n * @author Sebastian Daschner\n */\npublic final class JavaUtils {\n\n    public static final String INITIALIZER_NAME = \"<init>\";\n\n    private JavaUtils() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Checks if the given method name is a Java initializer.\n     *\n     * @param name The method name\n     * @return {@code true} if name is an initializer\n     */\n    public static boolean isInitializerName(final String name) {\n        return INITIALIZER_NAME.equals(name);\n    }\n\n    /**\n     * Returns the annotation or {@code null} if the element is not annotated with that type.\n     * <b>Note:</b> This step is necessary due to issues with external class loaders (e.g. Maven).\n     * The classes may not be identical and are therefore compared by FQ class name.\n     */\n    public static <A extends Annotation> A getAnnotation(final AnnotatedElement annotatedElement, final Class<A> annotationClass) {\n        final Optional<Annotation> annotation = Stream.of(annotatedElement.getAnnotations())\n                .filter(a -> a.annotationType().getName().equals(annotationClass.getName()))\n                .findAny();\n        return (A) annotation.orElse(null);\n    }\n\n    /**\n     * Checks if the annotation is present on the annotated element.\n     * <b>Note:</b> This step is necessary due to issues with external class loaders (e.g. Maven).\n     * The classes may not be identical and are therefore compared by FQ class name.\n     */\n    public static boolean isAnnotationPresent(final AnnotatedElement annotatedElement, final Class<?> annotationClass) {\n        return Stream.of(annotatedElement.getAnnotations()).map(Annotation::annotationType).map(Class::getName).anyMatch(n -> n.equals(annotationClass.getName()));\n    }\n\n    /**\n     * Determines the type which is most \"specific\" (i. e. parametrized types are more \"specific\" than generic types,\n     * types which are not {@link Object} are less specific). If no exact statement can be made, the first type is chosen.\n     *\n     * @param types The types\n     * @return The most \"specific\" type\n     */\n    public static String determineMostSpecificType(final String... types) {\n        switch (types.length) {\n            case 0:\n                throw new IllegalArgumentException(\"At least one type has to be provided\");\n            case 1:\n                return types[0];\n            case 2:\n                return determineMostSpecific(types[0], types[1]);\n            default:\n                String currentMostSpecific = determineMostSpecific(types[0], types[1]);\n                for (int i = 2; i < types.length; i++) {\n                    currentMostSpecific = determineMostSpecific(currentMostSpecific, types[i]);\n                }\n                return currentMostSpecific;\n        }\n    }\n\n    private static String determineMostSpecific(final String firstType, final String secondType) {\n        if (OBJECT.equals(secondType) || firstType.equals(secondType)) {\n            return firstType;\n        }\n\n        if (OBJECT.equals(firstType))\n            return secondType;\n\n        final List<String> firstTypeParameters = getTypeParameters(firstType);\n        final List<String> secondTypeParameters = getTypeParameters(secondType);\n        final boolean firstTypeParameterized = !firstTypeParameters.isEmpty();\n        final boolean secondTypeParameterized = !secondTypeParameters.isEmpty();\n\n        if (firstTypeParameterized || secondTypeParameterized) {\n            if (firstTypeParameterized && !secondTypeParameterized) {\n                return firstType;\n            }\n\n            if (!firstTypeParameterized) {\n                return secondType;\n            }\n\n            if (firstTypeParameters.size() != secondTypeParameters.size())\n                // types parameters are not compatible, no statement can be made\n                return firstType;\n\n            for (int i = 0; i < firstTypeParameters.size(); i++) {\n                final String firstInner = firstTypeParameters.get(i);\n                final String secondInner = secondTypeParameters.get(i);\n\n                if (firstInner.equals(secondInner)) continue;\n\n                // desired to test against identity, i.e. which object was taken by comparison\n                if (firstInner == determineMostSpecific(firstInner, secondInner))\n                    return firstType;\n                return secondType;\n            }\n        }\n\n        final boolean firstTypeArray = firstType.charAt(0) == '[';\n        final boolean secondTypeArray = secondType.charAt(0) == '[';\n\n        if (firstTypeArray || secondTypeArray) {\n            if (firstTypeArray && !secondTypeArray) {\n                return firstType;\n            }\n\n            if (!firstTypeArray) {\n                return secondType;\n            }\n        }\n\n        // check if one type is inherited from other\n        if (isAssignableTo(firstType, secondType)) return firstType;\n        if (isAssignableTo(secondType, firstType)) return secondType;\n\n        return firstType;\n    }\n\n    /**\n     * Determines the type which is least \"specific\" (i. e. parametrized types are more \"specific\" than generic types,\n     * types which are not {@link Object} are less specific). If no exact statement can be made, the second type is chosen.\n     *\n     * @param types The types\n     * @return The most \"specific\" type\n     * @see #determineMostSpecificType(String...)\n     */\n    public static String determineLeastSpecificType(final String... types) {\n        switch (types.length) {\n            case 0:\n                throw new IllegalArgumentException(\"At least one type has to be provided\");\n            case 1:\n                return types[0];\n            case 2:\n                return determineLeastSpecific(types[0], types[1]);\n            default:\n                String currentLeastSpecific = determineLeastSpecific(types[0], types[1]);\n                for (int i = 2; i < types.length; i++) {\n                    currentLeastSpecific = determineLeastSpecific(currentLeastSpecific, types[i]);\n                }\n                return currentLeastSpecific;\n        }\n    }\n\n    private static String determineLeastSpecific(final String firstType, final String secondType) {\n        final String mostSpecificType = determineMostSpecificType(firstType, secondType);\n        // has to compare identity to see which String object was taken\n        if (mostSpecificType == firstType)\n            return secondType;\n        return firstType;\n    }\n\n    /**\n     * Checks if the left type is assignable to the right type, i.e. the right type is of the same or a sub-type.\n     */\n    public static boolean isAssignableTo(final String leftType, final String rightType) {\n        if (leftType.equals(rightType))\n            return true;\n\n        final boolean firstTypeArray = leftType.charAt(0) == '[';\n        if (firstTypeArray ^ rightType.charAt(0) == '[') {\n            return false;\n        }\n\n        final Class<?> leftClass = loadClassFromType(leftType);\n        final Class<?> rightClass = loadClassFromType(rightType);\n        if (leftClass == null || rightClass == null)\n            return false;\n\n        final boolean bothTypesParameterized = hasTypeParameters(leftType) && hasTypeParameters(rightType);\n        return rightClass.isAssignableFrom(leftClass) && (firstTypeArray || !bothTypesParameterized || getTypeParameters(leftType).equals(getTypeParameters(rightType)));\n    }\n\n    private static boolean hasTypeParameters(final String type) {\n        return type.indexOf('<') >= 0;\n    }\n\n    /**\n     * Converts the given JVM object type signature to a class name. Erasures parametrized types.\n     * <p>\n     * Example: {@code Ljava/util/List<Ljava/lang/String;>; -> java/util/List}\n     *\n     * @throws IllegalArgumentException If the type is not a reference or array type.\n     */\n    public static String toClassName(final String type) {\n        switch (type.charAt(0)) {\n            case 'V':\n                return CLASS_PRIMITIVE_VOID;\n            case 'Z':\n                return CLASS_PRIMITIVE_BOOLEAN;\n            case 'C':\n                return CLASS_PRIMITIVE_CHAR;\n            case 'B':\n                return CLASS_PRIMITIVE_BYTE;\n            case 'S':\n                return CLASS_PRIMITIVE_SHORT;\n            case 'I':\n                return CLASS_PRIMITIVE_INT;\n            case 'F':\n                return CLASS_PRIMITIVE_FLOAT;\n            case 'J':\n                return CLASS_PRIMITIVE_LONG;\n            case 'D':\n                return CLASS_PRIMITIVE_DOUBLE;\n            case 'L':\n                final int typeParamStart = type.indexOf('<');\n                final int endIndex = typeParamStart >= 0 ? typeParamStart : type.indexOf(';');\n                return type.substring(1, endIndex);\n            case '[':\n            case '+':\n            case '-':\n                return toClassName(type.substring(1));\n            case 'T':\n                // TODO handle type variables\n                return CLASS_OBJECT;\n            default:\n                throw new IllegalArgumentException(\"Not a type signature: \" + type);\n        }\n    }\n\n    /**\n     * Converts the given JVM class name to a type signature.\n     * <p>\n     * Example: {@code java/util/List -> Ljava/util/List;}\n     */\n    public static String toType(final String className) {\n        return 'L' + className + ';';\n    }\n\n    /**\n     * Converts the given type signature to a human readable type string.\n     * <p>\n     * Example: {@code Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>; -> java.util.Map<java.lang.String, java.lang.String>}\n     */\n    public static String toReadableType(final String type) {\n        final SignatureReader reader = new SignatureReader(type);\n        final TraceSignatureVisitor visitor = new TraceSignatureVisitor(0);\n        reader.acceptType(visitor);\n        return visitor.getDeclaration();\n    }\n\n    /**\n     * Returns the JVM type signature of the given object.\n     */\n    public static String getType(final Object value) {\n        return Type.getDescriptor(value.getClass());\n    }\n\n    /**\n     * Returns the type parameters of the given type. Will be an empty list if the type is not parametrized.\n     */\n    public static List<String> getTypeParameters(final String type) {\n        if (type.charAt(0) != 'L')\n            return emptyList();\n\n        int lastStart = type.indexOf('<') + 1;\n        final List<String> parameters = new ArrayList<>();\n\n        if (lastStart > 0) {\n            int depth = 0;\n            for (int i = lastStart; i < type.length() - 2; i++) {\n                final char c = type.charAt(i);\n                if (c == '<')\n                    depth++;\n                else if (c == '>')\n                    depth--;\n                else if (c == ';' && depth == 0) {\n                    parameters.add(type.substring(lastStart, i + 1));\n                    lastStart = i + 1;\n                }\n            }\n        }\n        return parameters;\n    }\n\n    /**\n     * Returns the return type of the given method signature. Parametrized types are supported.\n     */\n    public static String getReturnType(final String methodSignature) {\n        return getReturnType(methodSignature, null);\n    }\n\n    public static String getReturnType(final String methodSignature, final String containedType) {\n        final String type = methodSignature.substring(methodSignature.lastIndexOf(')') + 1);\n        return resolvePotentialTypeVariables(type, containedType);\n    }\n\n    private static Map<String, String> getTypeVariables(final String type) {\n        if (type == null)\n            return emptyMap();\n        final Map<String, String> variables = new HashMap<>();\n        final List<String> actualTypeParameters = getTypeParameters(type);\n        final Class<?> loadedClass = loadClassFromType(type);\n        if (loadedClass == null) {\n            LogProvider.debug(\"could not load class for type \" + type);\n            return emptyMap();\n        }\n\n        final TypeVariable<? extends Class<?>>[] typeParameters = loadedClass.getTypeParameters();\n        for (int i = 0; i < actualTypeParameters.size(); i++) {\n            variables.put(typeParameters[i].getName(), actualTypeParameters.get(i));\n        }\n        return variables;\n    }\n\n    public static Class<?> loadClassFromName(final String className) {\n        switch (className) {\n            case CLASS_PRIMITIVE_VOID:\n                return int.class;\n            case CLASS_PRIMITIVE_BOOLEAN:\n                return boolean.class;\n            case CLASS_PRIMITIVE_CHAR:\n                return char.class;\n            case CLASS_PRIMITIVE_BYTE:\n                return byte.class;\n            case CLASS_PRIMITIVE_SHORT:\n                return short.class;\n            case CLASS_PRIMITIVE_INT:\n                return int.class;\n            case CLASS_PRIMITIVE_FLOAT:\n                return float.class;\n            case CLASS_PRIMITIVE_LONG:\n                return long.class;\n            case CLASS_PRIMITIVE_DOUBLE:\n                return double.class;\n        }\n\n        // TODO test for variable types\n\n        try {\n            return ContextClassReader.getClassLoader().loadClass(className.replace('/', '.'));\n        } catch (ClassNotFoundException e) {\n            LogProvider.error(\"Could not load class \" + className);\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n    public static Class<?> loadClassFromType(final String type) {\n        return loadClassFromName(toClassName(type));\n    }\n\n    public static Method findMethod(final String className, final String methodName, final String signature) {\n        final Class<?> loadedClass = loadClassFromName(className);\n        if (loadedClass == null)\n            return null;\n\n        return findMethod(loadedClass, methodName, signature);\n    }\n\n    public static Method findMethod(final Class<?> loadedClass, final String methodName, final String signature) {\n        final List<String> parameters = getParameters(signature);\n        return Stream.of(loadedClass.getDeclaredMethods()).filter(m -> m.getName().equals(methodName)\n                && m.getParameterCount() == parameters.size()\n                // return types are not taken into account (could be overloaded method w/ different return type)\n                && Objects.equals(getParameters(getMethodSignature(m)), parameters)\n        ).findAny().orElse(null);\n    }\n\n    public static String getMethodSignature(final String returnType, final String... parameterTypes) {\n        final String parameters = Stream.of(parameterTypes).collect(Collectors.joining());\n        return '(' + parameters + ')' + returnType;\n    }\n\n    public static String getMethodSignature(final Method method) {\n        try {\n            final Field signatureField = method.getClass().getDeclaredField(\"signature\");\n            signatureField.setAccessible(true);\n            final String signature = (String) signatureField.get(method);\n\n            if (signature != null)\n                return signature;\n            return Type.getMethodDescriptor(method);\n        } catch (ReflectiveOperationException e) {\n            LogProvider.error(\"Could not access method \" + method);\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n    public static String getFieldDescriptor(final Field field, final String containedType) {\n        try {\n            final Field signatureField = field.getClass().getDeclaredField(\"signature\");\n            signatureField.setAccessible(true);\n            String signature = (String) signatureField.get(field);\n            if (signature != null) {\n                return resolvePotentialTypeVariables(signature, containedType);\n\n            }\n            return Type.getDescriptor(field.getType());\n        } catch (ReflectiveOperationException e) {\n            LogProvider.error(\"Could not access field \" + field);\n            LogProvider.debug(e);\n            return null;\n        }\n    }\n\n    private static String resolvePotentialTypeVariables(final String signature, final String containedType) {\n        // resolve type variables immediately\n        if (signature.charAt(0) == 'T' || signature.contains(\"<T\") || signature.contains(\";T\") || signature.contains(\")T\")) {\n            // TODO test\n            final Map<String, String> typeVariables = getTypeVariables(containedType);\n            StringBuilder builder = new StringBuilder(signature);\n            boolean startType = true;\n\n            for (int i = 0; i < builder.length(); i++) {\n                if (startType && builder.charAt(i) == 'T') {\n                    final int end = builder.indexOf(\";\", i);\n                    final String identifier = builder.substring(i + 1, end);\n                    final String resolvedVariableType = typeVariables.getOrDefault(identifier, OBJECT);\n                    builder.replace(i, end + 1, resolvedVariableType);\n                    i = end;\n                    continue;\n                }\n                startType = builder.charAt(i) == '<' || builder.charAt(i) == ';';\n            }\n            return builder.toString();\n        }\n        return signature;\n    }\n\n    /**\n     * Returns the parameter types of the given method signature. Parametrized types are supported.\n     */\n    public static List<String> getParameters(final String methodDesc) {\n//        final String[] types = resolveMethodSignature(methodDesc);\n//        return IntStream.range(0, types.length).mapToObj(i -> types[i]).collect(Collectors.toList());\n        if (methodDesc == null)\n            return emptyList();\n\n        final char[] buffer = methodDesc.toCharArray();\n        final List<String> args = new ArrayList<>();\n\n        // TODO resolve type parameters correctly -> information useful? -> maybe use ASM's SignatureReader/Visitor\n        int offset = methodDesc.indexOf('(') + 1;\n        while (buffer[offset] != ')') {\n            final String type = getNextType(buffer, offset);\n            args.add(type);\n            offset += type.length();// + (type.charAt(0) == 'L' ? 2 : 0);\n        }\n\n        // TODO change, see type parameters\n        // prevent type parameter identifiers\n        final ListIterator<String> iterator = args.listIterator();\n        while (iterator.hasNext()) {\n            final String arg = iterator.next();\n            if (arg.charAt(0) == 'T')\n                iterator.set(OBJECT);\n        }\n\n        return args;\n    }\n\n    /**\n     * Resolves the given method signatures to an array of (self-contained) Java type descriptions.\n     *\n     * @param methodDesc The method description signature (can contain type parameters and generics)\n     * @return The types as an array with the method parameter types first and the return type as index {@code array.length - 1}\n     */\n    private static String[] resolveMethodSignature(final String methodDesc) {\n\n//         if starts with '<' -> resolve type parameters\n//        final Map<String, String> typeParameters = null;\n//        if (methodDesc.charAt(0) == '<') {\n//            typeParameters = resolveTypeParameters(methodDesc);\n//        }\n\n        return null;\n    }\n\n    private static Map<String, String> resolveTypeParameters(final String methodDesc) {\n//        boolean identifierMode = true;\n//        int identifierStart = 1;\n//        String currentIdentifier = null;\n//\n//        for (int i = 1; methodDesc.charAt(i) != '>'; i++) {\n//            switch (methodDesc.charAt(i)) {\n//                case ':':\n//                    if (identifierMode) {\n//                        identifierMode = false;\n//                        currentIdentifier = methodDesc.substring(identifierStart, i);\n//                    } else {\n//\n//                    }\n//            }\n//        }\n        return null;\n    }\n\n    private static String getNextType(final char[] buf, final int off) {\n        switch (buf[off]) {\n            case 'V':\n            case 'Z':\n            case 'C':\n            case 'B':\n            case 'S':\n            case 'I':\n            case 'F':\n            case 'J':\n            case 'D':\n                return String.valueOf(buf[off]);\n            case '[':\n                int len = 1;\n                while (buf[off + len] == '[') {\n                    len++;\n                }\n                return getNextType(buf, off, len);\n            case 'L':\n                // TODO resolve type variables\n            case 'T':\n                return getNextType(buf, off, 0);\n            default:\n                throw new IllegalArgumentException(\"Illegal signature provided: \" + new String(buf));\n        }\n    }\n\n    private static String getNextType(char[] buf, int off, int len) {\n        int depth = 0;\n        if (buf[off + len] == 'L' || buf[off + len] == 'T')\n            while (buf[off + len] != ';' || depth != 0) {\n                if (buf[off + len] == '<')\n                    depth++;\n                else if (buf[off + len] == '>')\n                    depth--;\n                len++;\n            }\n        return new String(buf, off, len + 1);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/Types.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * @author Sebastian Daschner\n */\npublic final class Types {\n\n    private Types() {\n        throw new UnsupportedOperationException();\n    }\n\n    public static final String OBJECT = \"Ljava/lang/Object;\";\n    public static final String CLASS = \"Ljava/lang/Class;\";\n\n    public static final String PATH = \"Ljavax/ws/rs/Path;\";\n    public static final String APPLICATION_PATH = \"Ljavax/ws/rs/ApplicationPath;\";\n    public static final String CONTEXT = \"Ljavax/ws/rs/core/Context;\";\n\n    public static final String CONSUMES = \"Ljavax/ws/rs/Consumes;\";\n    public static final String PRODUCES = \"Ljavax/ws/rs/Produces;\";\n\n    public static final String GET = \"Ljavax/ws/rs/GET;\";\n    public static final String POST = \"Ljavax/ws/rs/POST;\";\n    public static final String PUT = \"Ljavax/ws/rs/PUT;\";\n    public static final String DELETE = \"Ljavax/ws/rs/DELETE;\";\n    public static final String HEAD = \"Ljavax/ws/rs/HEAD;\";\n    public static final String OPTIONS = \"Ljavax/ws/rs/OPTIONS;\";\n    public static final String SUSPENDED = \"Ljavax/ws/rs/container/Suspended;\";\n\n    public static final String DEFAULT_VALUE = \"Ljavax/ws/rs/DefaultValue;\";\n    public static final String PATH_PARAM = \"Ljavax/ws/rs/PathParam;\";\n    public static final String QUERY_PARAM = \"Ljavax/ws/rs/QueryParam;\";\n    public static final String HEADER_PARAM = \"Ljavax/ws/rs/HeaderParam;\";\n    public static final String FORM_PARAM = \"Ljavax/ws/rs/FormParam;\";\n    public static final String COOKIE_PARAM = \"Ljavax/ws/rs/CookieParam;\";\n    public static final String MATRIX_PARAM = \"Ljavax/ws/rs/MatrixParam;\";\n\n    public static final String DEPRECATED = \"Ljava/lang/Deprecated;\";\n\n    public static final String PRIMITIVE_VOID = \"V\";\n    public static final String BOOLEAN = \"Ljava/lang/Boolean;\";\n    public static final String PRIMITIVE_BOOLEAN = \"Z\";\n    public static final String CHARACTER = \"Ljava/lang/Character;\";\n    public static final String PRIMITIVE_CHAR = \"C\";\n    public static final String INTEGER = \"Ljava/lang/Integer;\";\n    public static final String PRIMITIVE_INT = \"I\";\n    public static final String BYTE = \"Ljava/lang/Byte;\";\n    public static final String PRIMITIVE_BYTE = \"B\";\n    public static final String SHORT = \"Ljava/lang/Short;\";\n    public static final String PRIMITIVE_SHORT = \"S\";\n    public static final String DOUBLE = \"Ljava/lang/Double;\";\n    public static final String PRIMITIVE_DOUBLE = \"D\";\n    public static final String FLOAT = \"Ljava/lang/Float;\";\n    public static final String PRIMITIVE_FLOAT = \"F\";\n    public static final String LONG = \"Ljava/lang/Long;\";\n    public static final String PRIMITIVE_LONG = \"J\";\n    public static final String STRING = \"Ljava/lang/String;\";\n    public static final String THROWABLE = \"Ljava/lang/Throwable;\";\n    public static final String MAP = \"Ljava/util/Map;\";\n    public static final String LIST = \"Ljava/util/List;\";\n    public static final String SET = \"Ljava/util/Set;\";\n    public static final String COLLECTION = \"Ljava/util/Collection;\";\n    public static final String BIG_DECIMAL = \"Ljava/math/BigDecimal;\";\n    public static final String BIG_INTEGER = \"Ljava/math/BigInteger;\";\n    public static final String URI = \"Ljava/net/URI;\";\n    public static final String DATE = \"Ljava/util/Date;\";\n    public static final String TEMPORAL_ACCESSOR = \"Ljava/time/temporal/TemporalAccessor;\";\n    public static final String STREAM = \"Ljava/util/stream/Stream;\";\n    public static final String SUPPLIER = \"Ljava/util/function/Supplier;\";\n    public static final String BI_CONSUMER = \"Ljava/util/function/BiConsumer;\";\n    public static final String CONSUMER = \"Ljava/util/function/Consumer;\";\n\n    public static final String RESPONSE = \"Ljavax/ws/rs/core/Response;\";\n    public static final String RESPONSE_BUILDER = \"Ljavax/ws/rs/core/Response$ResponseBuilder;\";\n    public static final String RESPONSE_STATUS = \"Ljavax/ws/rs/core/Response$Status;\";\n    public static final String GENERIC_ENTITY = \"Ljavax/ws/rs/core/GenericEntity;\";\n    public static final String VARIANT = \"Ljavax/ws/rs/core/Variant;\";\n    public static final String ENTITY_TAG = \"Ljavax/ws/rs/core/EntityTag;\";\n\n    public static final String JSON = \"Ljavax/json/Json;\";\n    public static final String JSON_OBJECT_BUILDER = \"Ljavax/json/JsonObjectBuilder;\";\n    public static final String JSON_ARRAY_BUILDER = \"Ljavax/json/JsonArrayBuilder;\";\n    public static final String JSON_VALUE = \"Ljavax/json/JsonValue;\";\n    public static final String JSON_OBJECT = \"Ljavax/json/JsonObject;\";\n    public static final String JSON_ARRAY = \"Ljavax/json/JsonArray;\";\n\n    public static final String CLASS_OBJECT = \"java/lang/Object\";\n\n    public static final String CLASS_PRIMITIVE_VOID = \"void\";\n    public static final String CLASS_PRIMITIVE_BOOLEAN = \"boolean\";\n    public static final String CLASS_PRIMITIVE_CHAR = \"char\";\n    public static final String CLASS_PRIMITIVE_INT = \"int\";\n    public static final String CLASS_PRIMITIVE_BYTE = \"byte\";\n    public static final String CLASS_PRIMITIVE_SHORT = \"short\";\n    public static final String CLASS_PRIMITIVE_DOUBLE = \"double\";\n    public static final String CLASS_PRIMITIVE_FLOAT = \"float\";\n    public static final String CLASS_PRIMITIVE_LONG = \"long\";\n\n    public static final String CLASS_RESPONSE = \"javax/ws/rs/core/Response\";\n    public static final String CLASS_RESPONSE_BUILDER = \"javax/ws/rs/core/Response$ResponseBuilder\";\n    public static final String CLASS_RESOURCE_CONTEXT = \"javax/ws/rs/container/ResourceContext\";\n    public static final String CLASS_WEB_APPLICATION_EXCEPTION = \"javax/ws/rs/WebApplicationException\";\n\n    public static final String CLASS_LIST = \"java/util/List\";\n    public static final String CLASS_SET = \"java/util/Set\";\n    public static final String CLASS_INTEGER = \"java/lang/Integer\";\n    public static final String CLASS_DOUBLE = \"java/lang/Double\";\n    public static final String CLASS_LONG = \"java/lang/Long\";\n    public static final String CLASS_STREAM = \"java/util/stream/Stream\";\n\n    public static final String CLASS_JSON = \"javax/json/Json\";\n    public static final String CLASS_JSON_OBJECT_BUILDER = \"javax/json/JsonObjectBuilder\";\n    public static final String CLASS_JSON_ARRAY_BUILDER = \"javax/json/JsonArrayBuilder\";\n    public static final String CLASS_JSON_OBJECT = \"javax/json/JsonObject\";\n\n    public static final Set<String> PRIMITIVE_TYPES = new HashSet<>(Arrays.asList(PRIMITIVE_BOOLEAN, PRIMITIVE_VOID, PRIMITIVE_CHAR, PRIMITIVE_INT, PRIMITIVE_LONG,\n            PRIMITIVE_SHORT, PRIMITIVE_BYTE, PRIMITIVE_DOUBLE, PRIMITIVE_FLOAT));\n    public static final Set<String> PRIMITIVE_TYPES_ALL = new HashSet<>(Arrays.asList(PRIMITIVE_BOOLEAN, BOOLEAN, PRIMITIVE_VOID, PRIMITIVE_CHAR, CHARACTER,\n            PRIMITIVE_INT, INTEGER, PRIMITIVE_LONG, LONG, PRIMITIVE_SHORT, SHORT, PRIMITIVE_BYTE, BYTE, PRIMITIVE_DOUBLE, DOUBLE, PRIMITIVE_FLOAT, FLOAT));\n    public static final Set<String> INTEGER_TYPES = new HashSet<>(Arrays.asList(INTEGER, PRIMITIVE_INT, BIG_INTEGER, LONG, PRIMITIVE_LONG, SHORT, PRIMITIVE_SHORT,\n            BYTE, PRIMITIVE_BYTE));\n    public static final Set<String> DOUBLE_TYPES = new HashSet<>(Arrays.asList(DOUBLE, PRIMITIVE_DOUBLE, FLOAT, PRIMITIVE_FLOAT, BIG_DECIMAL));\n    public static final Set<String> JSON_TYPES = new HashSet<>(Arrays.asList(JSON_VALUE, JSON_OBJECT, JSON_ARRAY));\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/Element.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.OBJECT;\n\n/**\n * Represents an element on the runtime stack.\n *\n * @author Sebastian Daschner\n */\npublic class Element {\n\n    private final Set<Object> possibleValues;\n    private final Set<String> types;\n\n    public Element() {\n        this(Collections.singleton(OBJECT));\n    }\n\n    public Element(final String type, final Object... values) {\n        this(Collections.singleton(type), values);\n    }\n\n    public Element(final Set<String> types, final Object... values) {\n        Objects.requireNonNull(types);\n\n        this.types = new HashSet<>(types);\n        possibleValues = new HashSet<>();\n\n        // allow null as vararg argument\n        if (values == null)\n            possibleValues.add(null);\n        else\n            Collections.addAll(possibleValues, values);\n    }\n\n    /**\n     * Merges the other element into this element.\n     *\n     * @param element The element to merge\n     * @return This element (needed as BinaryOperator)\n     */\n    public Element merge(final Element element) {\n        types.addAll(element.types);\n        possibleValues.addAll(element.possibleValues);\n        return this;\n    }\n\n    public Set<Object> getPossibleValues() {\n        return possibleValues;\n    }\n\n    public Set<String> getTypes() {\n        return types;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final Element element = (Element) o;\n\n        if (!possibleValues.equals(element.possibleValues)) return false;\n        return types.equals(element.types);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = possibleValues.hashCode();\n        result = 31 * result + types.hashCode();\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"Element{\" +\n                \"possibleValues=\" + possibleValues +\n                \", types='\" + types + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/HttpResponse.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * @author Sebastian Daschner\n */\npublic class HttpResponse {\n\n    private final Set<Integer> statuses = new HashSet<>();\n    private final Set<String> headers = new HashSet<>();\n    private final Set<String> contentTypes = new HashSet<>();\n    private final Set<String> entityTypes = new HashSet<>();\n    private final Set<JsonValue> inlineEntities = new HashSet<>();\n\n    public Set<Integer> getStatuses() {\n        return statuses;\n    }\n\n    public Set<String> getHeaders() {\n        return headers;\n    }\n\n    public Set<String> getContentTypes() {\n        return contentTypes;\n    }\n\n    public Set<String> getEntityTypes() {\n        return entityTypes;\n    }\n\n    public Set<JsonValue> getInlineEntities() {\n        return inlineEntities;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final HttpResponse that = (HttpResponse) o;\n\n        if (!statuses.equals(that.statuses)) return false;\n        if (!headers.equals(that.headers)) return false;\n        if (!contentTypes.equals(that.contentTypes)) return false;\n        if (!entityTypes.equals(that.entityTypes)) return false;\n        return inlineEntities.equals(that.inlineEntities);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = statuses.hashCode();\n        result = 31 * result + headers.hashCode();\n        result = 31 * result + contentTypes.hashCode();\n        result = 31 * result + entityTypes.hashCode();\n        result = 31 * result + inlineEntities.hashCode();\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"HttpResponse{\" +\n                \"statuses=\" + statuses +\n                \", headers=\" + headers +\n                \", contentTypes=\" + contentTypes +\n                \", entityTypes=\" + entityTypes +\n                \", inlineEntities=\" + inlineEntities +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/JsonArray.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\n/**\n * Represents a JSON array element.\n *\n * @author Sebastian Daschner\n */\npublic class JsonArray implements JsonValue {\n\n    private final List<Element> elements = new LinkedList<>();\n\n    @Override\n    public JsonValue merge(final JsonValue element) {\n        elements.addAll(((JsonArray) element).elements);\n        return this;\n    }\n\n    public List<Element> getElements() {\n        return elements;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final JsonArray jsonArray = (JsonArray) o;\n\n        return elements.equals(jsonArray.elements);\n    }\n\n    @Override\n    public int hashCode() {\n        return elements.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"JsonArray{\" +\n                \"elements=\" + elements +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/JsonObject.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Represents a JSON object element.\n *\n * @author Sebastian Daschner\n */\npublic class JsonObject implements JsonValue {\n\n    private final Map<String, Element> structure = new HashMap<>();\n\n    @Override\n    public JsonValue merge(final JsonValue element) {\n        structure.putAll(((JsonObject) element).structure);\n        return this;\n    }\n\n    public Map<String, Element> getStructure() {\n        return structure;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final JsonObject that = (JsonObject) o;\n\n        return structure.equals(that.structure);\n    }\n\n    @Override\n    public int hashCode() {\n        return structure.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"JsonObject{\" +\n                \"structure=\" + structure +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/JsonValue.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\n/**\n * Marker interface for JSON value elements.\n *\n * @author Sebastian Daschner\n */\npublic interface JsonValue {\n\n    /**\n     * Merges the given value to this object.\n     *\n     * @param jsonValue The value to merge\n     * @return This object (needed as BinaryOperator)\n     */\n    JsonValue merge(JsonValue jsonValue);\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/elements/MethodHandle.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.elements;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodPool;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.Method;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\nimport java.util.stream.Stream;\n\n/**\n * Represents a method handle element on the stack.\n * The method handles are created when working with lambdas or method references.\n *\n * @author Sebastian Daschner\n */\npublic class MethodHandle extends Element implements Method {\n\n    /**\n     * The possible identifier of the method which are encapsulated.\n     */\n    private final Set<MethodIdentifier> possibleIdentifiers = new HashSet<>();\n\n    /**\n     * The arguments which are transferred from the bootstrap call to the later invoke.\n     */\n    private final List<Element> transferredArguments = new LinkedList<>();\n\n    public MethodHandle(final String returnType, final MethodIdentifier handleIdentifier, final List<Element> transferredArguments) {\n        super(returnType);\n        this.possibleIdentifiers.add(handleIdentifier);\n        this.transferredArguments.addAll(transferredArguments);\n    }\n\n    public MethodHandle(final MethodHandle methodHandle) {\n        super(methodHandle.getTypes());\n        this.possibleIdentifiers.addAll(methodHandle.possibleIdentifiers);\n        this.transferredArguments.addAll(methodHandle.transferredArguments);\n    }\n\n    public Set<MethodIdentifier> getPossibleIdentifiers() {\n        return possibleIdentifiers;\n    }\n\n    public List<Element> getTransferredArguments() {\n        return transferredArguments;\n    }\n\n    @Override\n    public Element invoke(final Element unused, final List<Element> arguments) {\n        // transfer invoke dynamic arguments\n        final List<Element> combinedArguments = Stream.concat(transferredArguments.stream(), arguments.stream()).collect(Collectors.toList());\n        return possibleIdentifiers.stream()\n                .map(i -> {\n                    final Method method = MethodPool.getInstance().get(i);\n                    if (!i.isStaticMethod()) {\n                        final List<Element> actualArguments = new ArrayList<>(combinedArguments);\n                        final Element object = actualArguments.isEmpty() ? new Element() : actualArguments.remove(0);\n                        if (JavaUtils.isInitializerName(i.getMethodName())) {\n                            return new Element(i.getContainingClass());\n                        }\n                        return method.invoke(object, actualArguments);\n                    }\n                    return method.invoke(null, combinedArguments);\n                })\n                .filter(Objects::nonNull).reduce(Element::merge).orElse(null);\n    }\n\n    @Override\n    public Element merge(final Element element) {\n        super.merge(element);\n        if (element instanceof MethodHandle) {\n            final MethodHandle methodHandle = (MethodHandle) element;\n            possibleIdentifiers.addAll(methodHandle.possibleIdentifiers);\n            IntStream.range(0, Math.max(transferredArguments.size(), methodHandle.transferredArguments.size()))\n                    .forEach(i -> {\n                        if (transferredArguments.size() < i && methodHandle.transferredArguments.size() < i)\n                            transferredArguments.get(i).merge(methodHandle.transferredArguments.get(i));\n                        // more arguments from second method handle will be ignored\n                    });\n        }\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"MethodHandle{\" +\n                \"possibleIdentifiers=\" + possibleIdentifiers +\n                \"transferredArguments=\" + transferredArguments +\n                \", type='\" + getTypes() + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/DefaultInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents an instruction which is not covered by other implementations of\n * {@link Instruction}.\n *\n * @author Sebastian Daschner\n */\npublic class DefaultInstruction extends Instruction {\n\n    private final String description;\n\n    public DefaultInstruction(final String description, final Label label) {\n        super(label);\n        this.description = description;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.OTHER;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 0;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final DefaultInstruction that = (DefaultInstruction) o;\n\n        if (getStackSizeDifference() != that.getStackSizeDifference()) return false;\n        if (getType() != that.getType()) return false;\n\n        return !(description != null ? !description.equals(that.description) : that.description != null);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = getStackSizeDifference();\n        result = 31 * result + (getType() != null ? getType().ordinal() : 0);\n        result = 31 * result + (description != null ? description.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"DefaultInstruction{\" +\n                \"type='\" + getType() + '\\'' +\n                \", description='\" + description + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/DupInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a DUP instruction.\n *\n * @author Sebastian Daschner\n */\npublic class DupInstruction extends Instruction {\n\n    public DupInstruction(final Label label) {\n        super(label);\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 1;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.DUP;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        return o != null && getClass() == o.getClass();\n\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    public String toString() {\n        return \"DupInstruction{}\";\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/ExceptionHandlerInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a dummy instruction which acts as an exception handler.\n *\n * @author Sebastian Daschner\n */\npublic class ExceptionHandlerInstruction extends SizeChangingInstruction {\n\n    private static final String DESCRIPTION = \"pseudoExceptionHandler\";\n\n    public ExceptionHandlerInstruction(final Label label) {\n        super(DESCRIPTION, 1, 0, label);\n    }\n\n    @Override\n    public String toString() {\n        return \"ExceptionHandlerInstruction{}\";\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/GetFieldInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a GET_FIELD instruction.\n *\n * @author Sebastian Daschner\n */\npublic class GetFieldInstruction extends GetPropertyInstruction {\n\n    public GetFieldInstruction(final String containingClass, final String fieldName, final String fieldType, final Label label) {\n        super(containingClass, fieldName, fieldType, label);\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.GET_FIELD;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 0;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/GetPropertyInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a GET_FIELD/STATIC instruction.\n *\n * @author Sebastian Daschner\n */\npublic abstract class GetPropertyInstruction extends Instruction {\n\n    private final String containingClass;\n    private final String propertyName;\n    private final String propertyType;\n\n    protected GetPropertyInstruction(final String containingClass, final String propertyName, final String propertyType, final Label label) {\n        super(label);\n        this.containingClass = containingClass;\n        this.propertyName = propertyName;\n        this.propertyType = propertyType;\n    }\n\n    public String getContainingClass() {\n        return containingClass;\n    }\n\n    public String getPropertyName() {\n        return propertyName;\n    }\n\n    public String getPropertyType() {\n        return propertyType;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final GetPropertyInstruction that = (GetPropertyInstruction) o;\n\n        if (containingClass != null ? !containingClass.equals(that.containingClass) : that.containingClass != null)\n            return false;\n        if (propertyName != null ? !propertyName.equals(that.propertyName) : that.propertyName != null) return false;\n        if (propertyType != null ? !propertyType.equals(that.propertyType) : that.propertyType != null) return false;\n        if (getStackSizeDifference() != that.getStackSizeDifference()) return false;\n\n        return getType() == that.getType();\n    }\n\n    @Override\n    public int hashCode() {\n        int result = containingClass != null ? containingClass.hashCode() : 0;\n        result = 31 * result + getStackSizeDifference();\n        result = 31 * result + (getType() != null ? getType().ordinal() : 0);\n        result = 31 * result + (propertyName != null ? propertyName.hashCode() : 0);\n        result = 31 * result + (propertyType != null ? propertyType.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"GetPropertyInstruction{\" +\n                \"type='\" + getType() + '\\'' +\n                \", containingClass='\" + containingClass + '\\'' +\n                \", propertyName='\" + propertyName + '\\'' +\n                \", propertyType='\" + propertyType + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/GetStaticInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a GET_STATIC instruction.\n *\n * @author Sebastian Daschner\n */\npublic class GetStaticInstruction extends GetPropertyInstruction {\n\n    private final Object value;\n\n    public GetStaticInstruction(final String containingClass, final String fieldName, final String fieldType, final Object value, final Label label) {\n        super(containingClass, fieldName, fieldType, label);\n        this.value = value;\n    }\n\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.GET_STATIC;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 1;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/Instruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a byte code instruction.\n *\n * @author Sebastian Daschner\n */\npublic abstract class Instruction {\n\n    private final Label label;\n\n    public Instruction(final Label label) {\n        this.label = label;\n    }\n\n    public abstract int getStackSizeDifference();\n\n    public abstract InstructionType getType();\n\n    public Label getLabel() {\n        return label;\n    }\n\n    /**\n     * Represents the available types of {@link Instruction}s.\n     */\n    public enum InstructionType {\n\n        PUSH, LOAD, STORE, INVOKE, RETURN, SIZE_CHANGE, GET_FIELD, GET_STATIC, NEW, DUP, THROW, METHOD_HANDLE, OTHER, LOAD_PLACEHOLDER, STORE_PLACEHOLDER\n\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/InvokeDynamicInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport org.objectweb.asm.Label;\n\nimport java.util.Objects;\n\n/**\n * Represents an INVOKE_DYNAMIC instruction which will push a method handle on the stack.\n *\n * @author Sebastian Daschner\n */\npublic class InvokeDynamicInstruction extends InvokeInstruction {\n\n    private final MethodIdentifier dynamicIdentifier;\n\n    public InvokeDynamicInstruction(final MethodIdentifier methodHandleIdentifier, final MethodIdentifier dynamicIdentifier, final Label label) {\n        super(methodHandleIdentifier, label);\n        Objects.requireNonNull(dynamicIdentifier);\n        this.dynamicIdentifier = dynamicIdentifier;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        // the method handle will be pushed on the stack\n        return 1 - dynamicIdentifier.getParameters().size();\n    }\n\n    public MethodIdentifier getDynamicIdentifier() {\n        return dynamicIdentifier;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.METHOD_HANDLE;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final InvokeDynamicInstruction that = (InvokeDynamicInstruction) o;\n\n        return dynamicIdentifier.equals(that.dynamicIdentifier);\n    }\n\n    @Override\n    public int hashCode() {\n        return dynamicIdentifier.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"InvokeDynamicInstruction{\" +\n                \"dynamicIdentifier='\" + dynamicIdentifier + '\\'' +\n                \", identifier='\" + getIdentifier() + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/InvokeInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport org.objectweb.asm.Label;\n\n/**\n * Represents an INVOKE_XYZ instruction.\n *\n * @author Sebastian Daschner\n */\npublic class InvokeInstruction extends Instruction {\n\n    private final MethodIdentifier identifier;\n\n    public InvokeInstruction(final MethodIdentifier identifier, final Label label) {\n        super(label);\n        this.identifier = identifier;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        int difference = Types.PRIMITIVE_VOID.equals(identifier.getReturnType()) ? -1 : 0;\n\n        if (identifier.isStaticMethod())\n            difference++;\n\n        difference -= identifier.getParameters().size();\n\n        return difference;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.INVOKE;\n    }\n\n    public MethodIdentifier getIdentifier() {\n        return identifier;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final InvokeInstruction that = (InvokeInstruction) o;\n\n        return identifier.equals(that.identifier);\n    }\n\n    @Override\n    public int hashCode() {\n        return identifier.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"InvokeInstruction{\" +\n                \"identifier=\" + identifier + '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/LoadInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a XZY_LOAD_X instruction (for any number).\n *\n * @author Sebastian Daschner\n */\npublic class LoadInstruction extends LoadStoreInstruction {\n\n    private final Label validUntil;\n\n    public LoadInstruction(final int number, final String variableType, final Label label, final Label validUntil) {\n        super(number, variableType, label);\n        this.validUntil = validUntil;\n    }\n\n    public LoadInstruction(final int number, final String variableType, final String name, final Label label, final Label validUntil) {\n        super(number, variableType, name, label);\n        this.validUntil = validUntil;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 1;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.LOAD;\n    }\n\n    public Label getValidUntil() {\n        return validUntil;\n    }\n\n    @Override\n    public String toString() {\n        return \"LoadInstruction{\" +\n                \"type='\" + getType() + '\\'' +\n                \", number=\" + getName() + '\\'' +\n                \", variableType=\" + getVariableType() + '\\'' +\n                \", name=\" + getName() +\n                \", validUntil=\" + validUntil +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/LoadStoreInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\nimport org.objectweb.asm.Label;\n\nimport java.util.Objects;\n\n/**\n * Represents any LOAD or STORE instruction.\n *\n * @author Sebastian Daschner\n */\npublic abstract class LoadStoreInstruction extends Instruction {\n\n    /**\n     * The variable name which is taken, if no information is found in the local variables attribute.\n     */\n    private static final String UNKNOWN_VARIABLE_NAME_PREFIX = \"variable$\";\n\n    private final int number;\n    private final String variableType;\n    private final String name;\n\n    protected LoadStoreInstruction(final int number, final String variableType, final Label label) {\n        super(label);\n        Objects.requireNonNull(variableType);\n\n        this.number = number;\n        this.variableType = variableType;\n        name = UNKNOWN_VARIABLE_NAME_PREFIX + number;\n    }\n\n    protected LoadStoreInstruction(final int number, final String variableType, final String name, final Label label) {\n        super(label);\n        Objects.requireNonNull(variableType);\n        StringUtils.requireNonBlank(name);\n\n        this.number = number;\n        this.variableType = variableType;\n        this.name = name;\n    }\n\n    public int getNumber() {\n        return number;\n    }\n\n    public String getVariableType() {\n        return variableType;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final LoadStoreInstruction that = (LoadStoreInstruction) o;\n\n        if (number != that.number) return false;\n        if (!name.equals(that.name)) return false;\n        if (!variableType.equals(that.variableType)) return false;\n        if (getStackSizeDifference() != that.getStackSizeDifference()) return false;\n\n        return getType() == that.getType();\n    }\n\n    @Override\n    public int hashCode() {\n        int result = number;\n        result = 31 * result + getStackSizeDifference();\n        result = 31 * result + (getType() != null ? getType().ordinal() : 0);\n        result = 31 * result + variableType.hashCode();\n        result = 31 * result + name.hashCode();\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"LoadStoreInstruction{\" +\n                \"type='\" + getType() + '\\'' +\n                \", number=\" + number +\n                \", variableType=\" + variableType +\n                \", name='\" + name + \"'}\";\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/LoadStoreInstructionPlaceholder.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * @author Sebastian Daschner\n */\npublic class LoadStoreInstructionPlaceholder extends Instruction {\n\n    private final InstructionType type;\n    private final int number;\n\n    public LoadStoreInstructionPlaceholder(final InstructionType type, final int number, final Label label) {\n        super(label);\n        if (!(type == InstructionType.LOAD_PLACEHOLDER || type == InstructionType.STORE_PLACEHOLDER))\n            throw new IllegalArgumentException(\"Only LOAD and STORE placeholders allowed!\");\n\n        this.type = type;\n        this.number = number;\n    }\n\n    public int getNumber() {\n        return number;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public InstructionType getType() {\n        return type;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final LoadStoreInstructionPlaceholder that = (LoadStoreInstructionPlaceholder) o;\n\n        if (number != that.number) return false;\n        return type == that.type;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = type.hashCode();\n        result = 31 * result + number;\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/NewInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\nimport java.util.Objects;\n\n/**\n * Represents a NEW instruction.\n *\n * @author Sebastian Daschner\n */\npublic class NewInstruction extends Instruction {\n\n    private final String className;\n\n    public NewInstruction(final String className, final Label label) {\n        super(label);\n        Objects.requireNonNull(className);\n\n        this.className = className;\n    }\n\n    public String getClassName() {\n        return className;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 1;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.NEW;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final NewInstruction that = (NewInstruction) o;\n\n        return className.equals(that.className);\n    }\n\n    @Override\n    public int hashCode() {\n        return className.hashCode();\n    }\n\n    @Override\n    public String toString() {\n        return \"NewInstruction{\" +\n                \"className='\" + className + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/PushInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents any instruction which pushes a constant value to the stack.\n *\n * @author Sebastian Daschner\n */\npublic class PushInstruction extends Instruction {\n\n    private final Object value;\n    private final String valueType;\n\n    public PushInstruction(final Object value, final String valueType, final Label label) {\n        super(label);\n        this.value = value;\n        this.valueType = valueType;\n    }\n\n    public Object getValue() {\n        return value;\n    }\n\n    public String getValueType() {\n        return valueType;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.PUSH;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return 1;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final PushInstruction that = (PushInstruction) o;\n\n        if (value != null ? !value.equals(that.value) : that.value != null) return false;\n        return valueType != null ? valueType.equals(that.valueType) : that.valueType == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = value != null ? value.hashCode() : 0;\n        result = 31 * result + (valueType != null ? valueType.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"PushInstruction{\" +\n                \"value=\" + value +\n                \", valueType='\" + valueType + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/ReturnInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents any RETURN instruction.\n *\n * @author Sebastian Daschner\n */\npublic class ReturnInstruction extends Instruction {\n\n    public ReturnInstruction(final Label label) {\n        super(label);\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.RETURN;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return -1;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        return o != null && getClass() == o.getClass();\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    public String toString() {\n        return \"ReturnInstruction{}\";\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/SizeChangingInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents any instruction which changes the stack elements and is not covered\n * by other implementations of {@link Instruction}.\n *\n * @author Sebastian Daschner\n */\npublic class SizeChangingInstruction extends DefaultInstruction {\n\n    private final int numberOfPushes;\n    private final int numberOfPops;\n\n    public SizeChangingInstruction(final String description, final int numberOfPushes, final int numberOfPops, final Label label) {\n        super(description, label);\n\n        if (numberOfPushes < 0 || numberOfPops < 0)\n            throw new IllegalArgumentException(\"Number of pushes and pops cannot be negative\");\n\n        this.numberOfPushes = numberOfPushes;\n        this.numberOfPops = numberOfPops;\n    }\n\n    public int getNumberOfPushes() {\n        return numberOfPushes;\n    }\n\n    public int getNumberOfPops() {\n        return numberOfPops;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.SIZE_CHANGE;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return numberOfPushes - numberOfPops;\n    }\n\n}"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/StoreInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a XZY_STORE_X instruction (for any number).\n *\n * @author Sebastian Daschner\n */\npublic class StoreInstruction extends LoadStoreInstruction {\n\n    public StoreInstruction(final int number, final String variableType, final Label label) {\n        super(number, variableType, label);\n    }\n\n    public StoreInstruction(final int number, final String variableType, final String name, final Label label) {\n        super(number, variableType, name, label);\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return -1;\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.STORE;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/instructions/ThrowInstruction.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.instructions;\n\nimport org.objectweb.asm.Label;\n\n/**\n * Represents a throw instruction.\n *\n * @author Sebastian Daschner\n */\npublic class ThrowInstruction extends Instruction {\n\n    public ThrowInstruction(final Label label) {\n        super(label);\n    }\n\n    @Override\n    public InstructionType getType() {\n        return InstructionType.THROW;\n    }\n\n    @Override\n    public int getStackSizeDifference() {\n        return -1;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        return o != null && getClass() == o.getClass();\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    public String toString() {\n        return \"ThrowInstruction{}\";\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/javadoc/ClassComment.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.javadoc;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ClassComment extends MemberComment {\n\n    private List<MemberParameterTag> fieldComments = new ArrayList<>();\n\n    public ClassComment() {\n        this(\"\", new HashMap<>(), false);\n    }\n\n    public ClassComment(String comment, Map<Integer, String> responseComments, boolean deprecated) {\n        super(comment, responseComments, deprecated);\n    }\n\n    public List<MemberParameterTag> getFieldComments() {\n        return fieldComments;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/javadoc/MemberComment.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.javadoc;\n\nimport java.util.Collections;\nimport java.util.Map;\n\npublic class MemberComment {\n\n    protected final String comment;\n    protected final boolean deprecated;\n    protected final Map<Integer, String> responseComments;\n\n    public MemberComment(String comment, Map<Integer, String> responseComments, boolean deprecated) {\n        this.comment = comment;\n        this.responseComments = Collections.unmodifiableMap(responseComments);\n        this.deprecated = deprecated;\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public boolean isDeprecated() {\n        return deprecated;\n    }\n\n    public Map<Integer, String> getResponseComments() {\n        return responseComments;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/javadoc/MemberParameterTag.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.javadoc;\n\nimport java.util.Collections;\nimport java.util.Map;\n\n/**\n * The comment parameter to a method parameter tag or a class field.\n * <p>\n * All types are not necessarily valid Java types but the simple names of the types.\n * Doing a full JavaDoc type resolving with all imports adds too much complexity at this point.\n * This is a best-effort approach.\n */\npublic class MemberParameterTag {\n\n    private final String comment;\n\n    /**\n     * The annotations with their type and {@code values()};\n     */\n    private final Map<String, String> annotations;\n\n    public MemberParameterTag(String comment, Map<String, String> annotations) {\n        this.comment = comment;\n        this.annotations = Collections.unmodifiableMap(annotations);\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public Map<String, String> getAnnotations() {\n        return annotations;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/javadoc/MethodComment.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.javadoc;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MethodComment extends MemberComment {\n\n    private final List<MemberParameterTag> paramTags;\n    private final ClassComment containingClassComment;\n\n    public MethodComment(String comment) {\n        this(comment, Collections.emptyList(), Collections.emptyMap(), null, false);\n    }\n\n    public MethodComment(String comment, List<MemberParameterTag> paramTags, Map<Integer, String> responseComments, ClassComment containingClassComment, boolean deprecated) {\n        super(comment, responseComments, deprecated);\n        this.paramTags = Collections.unmodifiableList(paramTags);\n        this.containingClassComment = containingClassComment;\n    }\n\n    public List<MemberParameterTag> getParamTags() {\n        return paramTags;\n    }\n\n    public ClassComment getContainingClassComment() {\n        return containingClassComment;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/methods/IdentifiableMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.methods;\n\n/**\n * Represents a method which is identifiable for a class name, method name and parameter types.\n *\n * @author Sebastian Daschner\n */\npublic interface IdentifiableMethod extends Method {\n\n    /**\n     * Checks if the given signature matches this method.\n     *\n     * @param identifier The method signature\n     * @return {@code true} if this method matches the signature\n     */\n    boolean matches(final MethodIdentifier identifier);\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/methods/Method.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.methods;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.InvokeInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\n\nimport java.util.List;\n\n/**\n * Represents a method which will be invoked via an {@link InvokeInstruction}.\n *\n * @author Sebastian Daschner\n */\npublic interface Method {\n\n    /**\n     * Invokes the method on the object with the given arguments.\n     *\n     * @param object    The object where the method is invoked ({@code null} for a static method)\n     * @param arguments The arguments of the method\n     * @return The method response or {@code null} for void\n     */\n    Element invoke(Element object, List<Element> arguments);\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/methods/MethodIdentifier.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.methods;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static java.util.Arrays.asList;\n\n/**\n * The method type signature with which a method can be identified.\n *\n * @author Sebastian Daschner\n */\npublic class MethodIdentifier {\n\n    /**\n     * The containing class as JVM class name, e.g. {@code java/lang/String}.\n     */\n    private final String containingClass;\n    private final String methodName;\n\n    /**\n     * The return type as JVM type descriptor, e.g. {@code Ljava/lang/String;}.\n     */\n    private final String returnType;\n    private final boolean staticMethod;\n    private final List<String> parameters;\n\n    private MethodIdentifier(final String containingClass, final String methodName, final List<String> parameters, final String returnType, final boolean staticMethod) {\n        Objects.requireNonNull(containingClass);\n        Objects.requireNonNull(methodName);\n        Objects.requireNonNull(returnType);\n\n        this.containingClass = containingClass;\n        this.methodName = methodName;\n        this.returnType = returnType;\n        this.staticMethod = staticMethod;\n        this.parameters = parameters;\n    }\n\n    /**\n     * Returns the method signature, e.g. {@code (Ljava/lang/String;)V}.\n     */\n    public String getSignature() {\n        final StringBuilder builder = new StringBuilder(\"(\");\n        parameters.forEach(builder::append);\n        return builder.append(')').append(returnType).toString();\n    }\n\n    public String getContainingClass() {\n        return containingClass;\n    }\n\n    public String getMethodName() {\n        return methodName;\n    }\n\n    public List<String> getParameters() {\n        return parameters;\n    }\n\n    public String getReturnType() {\n        return returnType;\n    }\n\n    public boolean isStaticMethod() {\n        return staticMethod;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        MethodIdentifier that = (MethodIdentifier) o;\n\n        if (staticMethod != that.staticMethod) return false;\n        if (!containingClass.equals(that.containingClass)) return false;\n        if (!methodName.equals(that.methodName)) return false;\n\n        if (parameters.equals(that.parameters))\n            return true;\n\n        // fallback if signature matches after type erasure\n        if (parameters.size() == that.parameters.size()) {\n            final List<String> erasedTypes = parameters.stream().map(JavaUtils::toClassName).collect(Collectors.toList());\n            final List<String> erasedThatTypes = that.parameters.stream().map(JavaUtils::toClassName).collect(Collectors.toList());\n            final String erasedReturnType = JavaUtils.toClassName(returnType);\n            final String erasedThatReturnType = JavaUtils.toClassName(that.returnType);\n            return erasedTypes.equals(erasedThatTypes) && erasedReturnType.equals(erasedThatReturnType);\n        }\n\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = containingClass.hashCode();\n        result = 31 * result + methodName.hashCode();\n        result = 31 * result + returnType.hashCode();\n        result = 31 * result + (staticMethod ? 1 : 0);\n        result = 31 * result + parameters.hashCode();\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"MethodIdentifier{\" +\n                \"containingClass='\" + containingClass + '\\'' +\n                \", methodName='\" + methodName + '\\'' +\n                \", returnType='\" + returnType + '\\'' +\n                \", staticMethod=\" + staticMethod +\n                \", parameters=\" + parameters +\n                '}';\n    }\n\n    /**\n     * Creates an identifier of the given parameters.\n     *\n     * @param containingClass The class name\n     * @param methodName      The method name\n     * @param signature       The method signature\n     * @param staticMethod    If the method is static\n     * @return The method identifier\n     */\n    public static MethodIdentifier of(final String containingClass, final String methodName, final String signature, final boolean staticMethod) {\n        final String returnType = JavaUtils.getReturnType(signature);\n        final List<String> parameters = JavaUtils.getParameters(signature);\n        return new MethodIdentifier(containingClass, methodName, parameters, returnType, staticMethod);\n    }\n\n    /**\n     * Creates an identifier of a non-static method.\n     *\n     * @param containingClass The class name\n     * @param methodName      The method name\n     * @param returnType      The return type\n     * @param parameterTypes  The parameter types\n     * @return The method identifier\n     */\n    public static MethodIdentifier ofNonStatic(final String containingClass, final String methodName, final String returnType, final String... parameterTypes) {\n        return of(containingClass, methodName, returnType, false, parameterTypes);\n    }\n\n    /**\n     * Creates an identifier of a static method.\n     *\n     * @param containingClass The class name\n     * @param methodName      The method name\n     * @param returnType      The return type\n     * @param parameterTypes  The parameter types\n     * @return The method identifier\n     */\n    public static MethodIdentifier ofStatic(final String containingClass, final String methodName, final String returnType, final String... parameterTypes) {\n        return of(containingClass, methodName, returnType, true, parameterTypes);\n    }\n\n    private static MethodIdentifier of(String containingClass, String methodName, String returnType, final boolean staticMethod, String[] parameterTypes) {\n        Objects.requireNonNull(parameterTypes);\n\n        return new MethodIdentifier(containingClass, methodName, asList(parameterTypes), returnType, staticMethod);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/methods/ProjectMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.methods;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.InjectableArgumentMethodSimulator;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\n\nimport java.util.List;\n\n/**\n * Represents a method which is defined in the analyzed project and will be invoked at interpret time with the correct arguments.\n *\n * @author Sebastian Daschner\n */\npublic class ProjectMethod implements IdentifiableMethod {\n\n    private final MethodIdentifier identifier;\n    private final List<Instruction> instructions;\n\n    public ProjectMethod(final MethodIdentifier identifier, final List<Instruction> instructions) {\n        this.identifier = identifier;\n        this.instructions = instructions;\n    }\n\n    @Override\n    public boolean matches(final MethodIdentifier identifier) {\n        return this.identifier.equals(identifier);\n    }\n\n    @Override\n    public Element invoke(final Element object, final List<Element> arguments) {\n        return new InjectableArgumentMethodSimulator().simulate(arguments, instructions, identifier);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/HttpMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\n/**\n * Represents the default HTTP methods.\n *\n * @author Sebastian Daschner\n */\npublic enum HttpMethod {\n    GET, PUT, POST, DELETE, OPTIONS, HEAD, PATCH\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/MethodParameter.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\n/**\n * Represents a single resource method parameter (like query parameter, header field, path parameter, etc.).\n *\n * @author Daryl Teo\n * @author Sebastian Daschner\n */\npublic class MethodParameter {\n\n    /**\n     * The type of the Java property (field or parameter).\n     * Only String, primitive types, enums or collections of these (no nested levels) are allowed.\n     */\n    private TypeIdentifier type;\n    private ParameterType parameterType;\n    private String name;\n    private String description;\n    private String defaultValue;\n\n    public MethodParameter(final TypeIdentifier type) {\n        this.type = type;\n    }\n\n    public MethodParameter(final TypeIdentifier type, final ParameterType parameterType) {\n        this.type = type;\n        this.parameterType = parameterType;\n    }\n\n    public TypeIdentifier getType() {\n        return type;\n    }\n\n    public void setType(final TypeIdentifier type) {\n        this.type = type;\n    }\n\n    public ParameterType getParameterType() {\n        return parameterType;\n    }\n\n    public void setParameterType(final ParameterType parameterType) {\n        this.parameterType = parameterType;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(final String name) {\n        this.name = name;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(final String description) {\n        this.description = description;\n    }\n\n    public String getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(final String defaultValue) {\n        this.defaultValue = defaultValue;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final MethodParameter that = (MethodParameter) o;\n\n        if (type != null ? !type.equals(that.type) : that.type != null) return false;\n        if (parameterType != that.parameterType) return false;\n        if (name != null ? !name.equals(that.name) : that.name != null) return false;\n        if (description != null ? !description.equals(that.description) : that.description != null) return false;\n        return defaultValue != null ? defaultValue.equals(that.defaultValue) : that.defaultValue == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = type != null ? type.hashCode() : 0;\n        result = 31 * result + (parameterType != null ? parameterType.hashCode() : 0);\n        result = 31 * result + (name != null ? name.hashCode() : 0);\n        result = 31 * result + (description != null ? description.hashCode() : 0);\n        result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"MethodParameter{\" +\n                \"type=\" + type +\n                \", parameterType=\" + parameterType +\n                \", name='\" + name + '\\'' +\n                \", description='\" + description + '\\'' +\n                \", defaultValue='\" + defaultValue + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/ParameterType.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\n/**\n * The available parameter types. Needed for identification in {@link MethodParameter}.\n *\n * @author Sebastian Daschner\n */\npublic enum ParameterType {\n\n    PATH, QUERY, HEADER, FORM, MATRIX, COOKIE\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/Project.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\n/**\n * A REST project.\n *\n * @author Sebastian Daschner\n */\npublic class Project {\n\n    private final String name;\n    private final String version;\n    private final Resources resources;\n\n    public Project(final String name, final String version, final Resources resources) {\n        StringUtils.requireNonBlank(name);\n        StringUtils.requireNonBlank(version);\n        this.name = name;\n        this.version = version;\n        this.resources = resources;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public Resources getResources() {\n        return resources;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/ResourceMethod.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/**\n * Represents a REST resource method.\n *\n * @author Sebastian Daschner\n */\npublic class ResourceMethod {\n\n    private final Set<String> requestMediaTypes = new HashSet<>();\n    private final Set<String> responseMediaTypes = new HashSet<>();\n    private final Map<Integer, Response> responses = new HashMap<>();\n    private final Set<MethodParameter> methodParameters = new HashSet<>();\n    private String description;\n\n    private HttpMethod method;\n    private TypeIdentifier requestBody;\n    private String requestBodyDescription;\n    private boolean deprecated;\n\n    public ResourceMethod() {\n    }\n\n    public ResourceMethod(final HttpMethod method, final String description) {\n        Objects.requireNonNull(method);\n        this.method = method;\n        this.description = description;\n    }\n\n    public HttpMethod getMethod() {\n        return method;\n    }\n\n    public Set<MethodParameter> getMethodParameters() {\n        return methodParameters;\n    }\n\n    public TypeIdentifier getRequestBody() {\n        return requestBody;\n    }\n\n    public void setRequestBody(final TypeIdentifier requestBody) {\n        this.requestBody = requestBody;\n    }\n\n    public Set<String> getRequestMediaTypes() {\n        return requestMediaTypes;\n    }\n\n    public Set<String> getResponseMediaTypes() {\n        return responseMediaTypes;\n    }\n\n    public Map<Integer, Response> getResponses() {\n        return responses;\n    }\n\n    public boolean isDeprecated() {\n        return deprecated;\n    }\n\n    public void setDeprecated(boolean deprecated) {\n        this.deprecated = deprecated;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public String getRequestBodyDescription() {\n        return requestBodyDescription;\n    }\n\n    public void setRequestBodyDescription(final String requestBodyDescription) {\n        this.requestBodyDescription = requestBodyDescription;\n    }\n\n    public ResourceMethod combine(ResourceMethod with) {\n        ResourceMethod rm = new ResourceMethod();\n        rm.method = with.method;\n        rm.requestBody = with.requestBody;\n\n        rm.requestMediaTypes.addAll(this.requestMediaTypes);\n        rm.requestMediaTypes.addAll(with.requestMediaTypes);\n\n        rm.responseMediaTypes.addAll(this.responseMediaTypes);\n        rm.responseMediaTypes.addAll(with.responseMediaTypes);\n\n        rm.responses.putAll(this.responses);\n        rm.responses.putAll(with.responses);\n\n        rm.methodParameters.addAll(this.methodParameters);\n        rm.methodParameters.addAll(with.methodParameters);\n\n        String combinedDescription = Stream.of(this.description, with.description)\n                .filter(s -> !StringUtils.isBlank(s))\n                .collect(Collectors.joining(\"\\n\"));\n        rm.description = StringUtils.isBlank(combinedDescription) ? null : combinedDescription;\n\n        rm.requestBodyDescription = mergeRequestBodyDescription(with);\n\n        rm.deprecated = Stream.of(this.deprecated, with.deprecated).anyMatch(Boolean.TRUE::equals);\n        return rm;\n    }\n\n    private String mergeRequestBodyDescription(ResourceMethod other) {\n        final boolean thisNull = requestBodyDescription == null;\n        final boolean otherNull = other.requestBodyDescription == null;\n        if (thisNull && otherNull)\n            return null;\n\n        if (thisNull ^ otherNull)\n            return thisNull ? other.requestBodyDescription : requestBodyDescription;\n\n        return requestBodyDescription + \"\\n\" + other.requestBodyDescription;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final ResourceMethod that = (ResourceMethod) o;\n\n        if (!requestMediaTypes.equals(that.requestMediaTypes)) return false;\n        if (!responseMediaTypes.equals(that.responseMediaTypes)) return false;\n        if (!responses.equals(that.responses)) return false;\n        if (!methodParameters.equals(that.methodParameters)) return false;\n        if (method != that.method) return false;\n        if (deprecated != that.deprecated) return false;\n        if (description != null ? !description.equals(that.description) : that.description != null) return false;\n        if (requestBodyDescription != null ? !requestBodyDescription.equals(that.requestBodyDescription) : that.requestBodyDescription != null)\n            return false;\n        return requestBody != null ? requestBody.equals(that.requestBody) : that.requestBody == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = requestMediaTypes.hashCode();\n        result = 31 * result + responseMediaTypes.hashCode();\n        result = 31 * result + responses.hashCode();\n        result = 31 * result + methodParameters.hashCode();\n        result = 31 * result + method.hashCode();\n        result = 31 * result + (deprecated ? 1231 : 1237);\n        result = 31 * result + (description != null ? description.hashCode() : 0);\n        result = 31 * result + (requestBodyDescription != null ? requestBodyDescription.hashCode() : 0);\n        result = 31 * result + (requestBody != null ? requestBody.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"ResourceMethod{\" +\n                \"method=\" + method +\n                \", requestMediaTypes=\" + requestMediaTypes +\n                \", responseMediaTypes=\" + responseMediaTypes +\n                \", responses=\" + responses +\n                \", methodParameters=\" + methodParameters +\n                \", description=\" + description +\n                \", requestBodyDescription=\" + requestBodyDescription +\n                \", requestBody=\" + requestBody +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/Resources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\n/**\n * Represents a set of resources and their possible methods.\n *\n * @author Sebastian Daschner\n */\npublic class Resources {\n\n    private Map<String, Set<ResourceMethod>> resources = new HashMap<>();\n    private final Map<TypeIdentifier, TypeRepresentation> typeRepresentations = new HashMap<>();\n    private String basePath;\n\n    /**\n     * Adds the method to the resource's methods.\n     *\n     * @param resource The resource path where to add\n     * @param method   The method to add\n     */\n    public void addMethod(final String resource, final ResourceMethod method) {\n        resources.putIfAbsent(resource, new HashSet<>());\n        resources.get(resource).add(method);\n    }\n\n    /**\n     * Returns all resource paths.\n     *\n     * @return The resources\n     */\n    public Set<String> getResources() {\n        return Collections.unmodifiableSet(resources.keySet());\n    }\n\n    /**\n     * Returns the resource methods for a given resource.\n     *\n     * @param resource The resource path\n     * @return The methods\n     */\n    public Set<ResourceMethod> getMethods(final String resource) {\n        return Collections.unmodifiableSet(resources.get(resource));\n    }\n\n    /**\n     * Checks if the resources contain reasonable data, i.e. actual methods mapped to resources.\n     */\n    public boolean isEmpty() {\n        return resources.isEmpty() || resources.values().stream().allMatch(Set::isEmpty);\n    }\n\n    /**\n     * Consolidates the information contained in multiple responses for the same path.\n     * Internally creates new resources.\n     */\n    public void consolidateMultiplePaths() {\n        Map<String, Set<ResourceMethod>> oldResources = resources;\n        resources = new HashMap<>();\n\n        oldResources.keySet().forEach(s -> consolidateMultipleMethodsForSamePath(s, oldResources.get(s)));\n    }\n\n    private void consolidateMultipleMethodsForSamePath(String path, Set<ResourceMethod> resourceMethods) {\n        resourceMethods.stream()\n                .collect(Collectors.groupingBy(m -> m.getMethod().toString().toLowerCase(),\n                        Collectors.reducing(new ResourceMethod(), ResourceMethod::combine))\n                ).forEach((k, v) -> addMethod(path, v));\n    }\n\n    public Map<TypeIdentifier, TypeRepresentation> getTypeRepresentations() {\n        return typeRepresentations;\n    }\n\n    public String getBasePath() {\n        return basePath;\n    }\n\n    public void setBasePath(final String basePath) {\n        this.basePath = basePath;\n    }\n\n    @Override\n    public boolean equals(Object object) {\n        if (this == object) return true;\n        if (object == null || getClass() != object.getClass()) return false;\n\n        Resources that = (Resources) object;\n\n        if (!resources.equals(that.resources)) return false;\n        if (!typeRepresentations.equals(that.typeRepresentations)) return false;\n        return !(basePath != null ? !basePath.equals(that.basePath) : that.basePath != null);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = resources.hashCode();\n        result = 31 * result + typeRepresentations.hashCode();\n        result = 31 * result + (basePath != null ? basePath.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"Resources{\" +\n                \"resources=\" + resources +\n                \", typeRepresentations=\" + typeRepresentations +\n                \", basePath='\" + basePath + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/Response.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Represents a response containing meta information which is sent for a specific status code.\n *\n * @author Sebastian Daschner\n */\npublic class Response {\n\n    private final Set<String> headers = new HashSet<>();\n    private final TypeIdentifier responseBody;\n    private final String description;\n\n    public Response() {\n        this(null,null);\n    }\n\n    public Response(final TypeIdentifier responseBody) {\n        this.responseBody = responseBody;\n        this.description = null;\n    }\n\n    public Response(TypeIdentifier responseBody, String description) {\n        this.responseBody = responseBody;\n        this.description = description;\n    }\n\n    public Set<String> getHeaders() {\n        return headers;\n    }\n\n    public TypeIdentifier getResponseBody() {\n        return responseBody;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        Response response = (Response) o;\n\n        if (!headers.equals(response.headers)) return false;\n        return !(responseBody != null ? !responseBody.equals(response.responseBody) : response.responseBody != null);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = headers.hashCode();\n        result = 31 * result + (responseBody != null ? responseBody.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"Response{\" +\n                \"headers=\" + headers +\n                \", responseBody=\" + responseBody +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/TypeIdentifier.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Identifies a type representation.\n * A type identifier is either a Java type or an &quo;dynamic&quo; type (i.e. a {@link javax.json.JsonValue}).\n *\n * @author Sebastian Daschner\n */\npublic abstract class TypeIdentifier {\n\n    public static final String DYNAMIC_TYPE_PREFIX = \"$\";\n    private static final AtomicInteger dynamicCounter = new AtomicInteger();\n\n    @Override\n    public abstract boolean equals(final Object object);\n\n    public abstract String getType();\n\n    public abstract String getName();\n\n    public static TypeIdentifier ofType(final String type) {\n        return new JavaTypeIdentifier(type);\n    }\n\n    public static TypeIdentifier ofDynamic() {\n        return new DynamicTypeIdentifier(dynamicCounter.incrementAndGet());\n    }\n\n    private static class JavaTypeIdentifier extends TypeIdentifier {\n        private final String type;\n\n        public JavaTypeIdentifier(final String type) {\n            Objects.requireNonNull(type);\n            this.type = type;\n        }\n\n        @Override\n        public String getType() {\n            return type;\n        }\n\n        @Override\n        public String getName() {\n            return type;\n        }\n\n        @Override\n        public boolean equals(final Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n\n            JavaTypeIdentifier that = (JavaTypeIdentifier) o;\n\n            return type.equals(that.type);\n        }\n\n        @Override\n        public int hashCode() {\n            return type.hashCode();\n        }\n\n        @Override\n        public String toString() {\n            return \"JavaTypeIdentifier{\" +\n                    \"type=\" + type +\n                    '}';\n        }\n    }\n\n    private static class DynamicTypeIdentifier extends TypeIdentifier {\n\n        private final int number;\n\n        public DynamicTypeIdentifier(final int number) {\n            this.number = number;\n        }\n\n        @Override\n        public String getType() {\n            return Types.JSON;\n        }\n\n        @Override\n        public String getName() {\n            return DYNAMIC_TYPE_PREFIX + number;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n\n            DynamicTypeIdentifier that = (DynamicTypeIdentifier) o;\n\n            return number == that.number;\n        }\n\n        @Override\n        public int hashCode() {\n            return number;\n        }\n\n        @Override\n        public String toString() {\n            return \"DynamicTypeIdentifier{\" +\n                    \"number=\" + number +\n                    '}';\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/TypeRepresentation.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.util.*;\n\n/**\n * Represents a request/response body type including the properties which actually will be serialized (e.g. depending on the JAXB mapping).\n * Enables the {@link TypeRepresentationVisitor}s to access the recursive model.\n *\n * @author Sebastian Daschner\n */\npublic abstract class TypeRepresentation {\n\n    private final TypeIdentifier identifier;\n\n    private TypeRepresentation(final TypeIdentifier identifier) {\n        this.identifier = identifier;\n    }\n\n    public abstract void accept(final TypeRepresentationVisitor visitor);\n\n    public TypeIdentifier getIdentifier() {\n        return identifier;\n    }\n\n    /**\n     * Returns the component type which is either the actual type identifier or the contained type for a collection type.\n     *\n     * @return The component type\n     */\n    public abstract TypeIdentifier getComponentType();\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        TypeRepresentation that = (TypeRepresentation) o;\n        return identifier.equals(that.identifier);\n    }\n\n    @Override\n    public int hashCode() {\n        return identifier.hashCode();\n    }\n\n    /**\n     * Creates a type representation of a concrete type (i.e. a Java type, not a programmatically created type) without actual properties.\n     * This is used for JDK internal types (like {@link String}, {@link Object}) where no property analysis is desired.\n     *\n     * @param identifier The type identifier\n     * @return The type representation\n     */\n    public static TypeRepresentation ofConcrete(final TypeIdentifier identifier) {\n        return new ConcreteTypeRepresentation(identifier, Collections.emptyMap());\n    }\n\n    /**\n     * Creates a type representation of a concrete type (i.e. a Java type, not a programmatically created type) plus the actual properties.\n     *\n     * @param identifier The type identifier\n     * @param properties The type (POJO) description\n     * @return The type representation\n     */\n    public static TypeRepresentation ofConcrete(final TypeIdentifier identifier, final Map<String, TypeIdentifier> properties) {\n        return new ConcreteTypeRepresentation(identifier, properties);\n    }\n\n    /**\n     * Creates a type representation of a collection type (i.e. anything assignable to {@link java.util.Collection} or an array) which contains an actual representation.\n     * <p>\n     * Example: {@code identifier: java.util.List<java.lang.String>, typeRepresentation: java.lang.String}\n     *\n     * @param identifier         The type identifier of the collection type\n     * @param typeRepresentation The contained type representation\n     * @return The type representation\n     */\n    public static TypeRepresentation ofCollection(final TypeIdentifier identifier, final TypeRepresentation typeRepresentation) {\n        return new CollectionTypeRepresentation(identifier, typeRepresentation);\n    }\n\n    /**\n     * Creates a type representation of an enum type plus the available enumeration values.\n     *\n     * @param identifier The type identifier\n     * @param enumValues The enum values\n     * @return The type representation\n     */\n    public static TypeRepresentation ofEnum(final TypeIdentifier identifier, final String... enumValues) {\n        return new EnumTypeRepresentation(identifier, new HashSet<>(Arrays.asList(enumValues)));\n    }\n\n    public static class ConcreteTypeRepresentation extends TypeRepresentation {\n\n        private final Map<String, TypeIdentifier> properties;\n\n        private ConcreteTypeRepresentation(final TypeIdentifier identifier, final Map<String, TypeIdentifier> properties) {\n            super(identifier);\n            this.properties = properties;\n        }\n\n        public Map<String, TypeIdentifier> getProperties() {\n            return properties;\n        }\n\n        @Override\n        public TypeIdentifier getComponentType() {\n            return getIdentifier();\n        }\n\n        @Override\n        public void accept(final TypeRepresentationVisitor visitor) {\n            visitor.visit(this);\n        }\n\n        /**\n         * Checks if the properties of this representation matches the given properties.\n         *\n         * @param properties The other properties to check\n         * @return {@code true} if the content equals\n         */\n        public boolean contentEquals(final Map<String, TypeIdentifier> properties) {\n            return this.properties.equals(properties);\n        }\n\n        @Override\n        public String toString() {\n            return \"ConcreteTypeRepresentation{\" +\n                    \"identifier=\" + getIdentifier() +\n                    \",properties=\" + properties +\n                    '}';\n        }\n    }\n\n    public static class CollectionTypeRepresentation extends TypeRepresentation {\n\n        private final TypeRepresentation representation;\n\n        private CollectionTypeRepresentation(final TypeIdentifier identifier, final TypeRepresentation representation) {\n            super(identifier);\n            this.representation = representation;\n        }\n\n        public TypeRepresentation getRepresentation() {\n            return representation;\n        }\n\n        @Override\n        public TypeIdentifier getComponentType() {\n            return representation.getIdentifier();\n        }\n\n        @Override\n        public void accept(final TypeRepresentationVisitor visitor) {\n            visitor.visitStart(this);\n            representation.accept(visitor);\n            visitor.visitEnd(this);\n        }\n\n        /**\n         * Checks if the nested type of this collection representation matches the given type (i.e. the same property bindings for concrete types\n         * or the same contained representation for collection types). This does not check the actual type (identifier).\n         *\n         * @param representation The other nested representation to check\n         * @return {@code true} if the content equals\n         */\n        public boolean contentEquals(final TypeRepresentation representation) {\n            final boolean thisStaticType = !this.representation.getIdentifier().getType().equals(Types.JSON);\n            final boolean otherStaticType = !representation.getIdentifier().getType().equals(Types.JSON);\n\n            if (thisStaticType ^ otherStaticType)\n                return false;\n\n            if (thisStaticType)\n                return this.representation.getIdentifier().equals(representation.getIdentifier());\n\n            final boolean thisCollection = this.representation instanceof CollectionTypeRepresentation;\n            final boolean thatCollection = representation instanceof CollectionTypeRepresentation;\n            if (thisCollection ^ thatCollection)\n                return false;\n\n            if (thisCollection)\n                return ((CollectionTypeRepresentation) this.representation).contentEquals(((CollectionTypeRepresentation) representation).getRepresentation());\n\n            return ((ConcreteTypeRepresentation) this.representation).contentEquals(((ConcreteTypeRepresentation) representation).getProperties());\n        }\n\n        @Override\n        public String toString() {\n            return \"CollectionTypeRepresentation{\" +\n                    \"identifier=\" + getIdentifier() +\n                    \",representation=\" + representation +\n                    '}';\n        }\n    }\n\n    public static class EnumTypeRepresentation extends TypeRepresentation {\n\n        private final Set<String> enumValues;\n\n        private EnumTypeRepresentation(final TypeIdentifier identifier, final Set<String> enumValues) {\n            super(identifier);\n            this.enumValues = enumValues;\n        }\n\n        public Set<String> getEnumValues() {\n            return enumValues;\n        }\n\n        @Override\n        public void accept(final TypeRepresentationVisitor visitor) {\n            visitor.visit(this);\n        }\n\n        @Override\n        public TypeIdentifier getComponentType() {\n            return getIdentifier();\n        }\n\n        @Override\n        public String toString() {\n            return \"EnumTypeRepresentation{\" +\n                    \"enumValues=\" + enumValues +\n                    '}';\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/TypeRepresentationVisitor.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\n/**\n * Visitor for the {@link TypeRepresentation} implementations.\n *\n * @author Sebastian Daschner\n */\npublic interface TypeRepresentationVisitor {\n\n    void visit(TypeRepresentation.ConcreteTypeRepresentation representation);\n\n    void visitStart(TypeRepresentation.CollectionTypeRepresentation representation);\n    void visitEnd(TypeRepresentation.CollectionTypeRepresentation representation);\n\n    void visit(TypeRepresentation.EnumTypeRepresentation representation);\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/results/ClassResult.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Represents a resource class result.\n *\n * @author Sebastian Daschner\n */\npublic class ClassResult {\n\n    private String applicationPath;\n    private String resourcePath;\n    private String originalClass;\n    private final Set<MethodParameter> classFields = new HashSet<>();\n    private final Set<MethodResult> methods = new HashSet<>();\n    private final Set<String> requestMediaTypes = new HashSet<>();\n    private final Set<String> responseMediaTypes = new HashSet<>();\n    private MethodResult parentSubResourceLocator;\n    private boolean deprecated;\n\n    public String getApplicationPath() {\n        return applicationPath;\n    }\n\n    public void setApplicationPath(final String applicationPath) {\n        this.applicationPath = applicationPath;\n    }\n\n    public String getResourcePath() {\n        return resourcePath;\n    }\n\n    public void setResourcePath(final String resourcePath) {\n        this.resourcePath = resourcePath;\n    }\n\n    public String getOriginalClass() {\n        return originalClass;\n    }\n\n    public void setOriginalClass(String originalClass) {\n        this.originalClass = originalClass;\n    }\n\n    public Set<MethodParameter> getClassFields() {\n        return classFields;\n    }\n\n    public Set<MethodResult> getMethods() {\n        return Collections.unmodifiableSet(methods);\n    }\n\n    public void add(final MethodResult methodResult) {\n        methods.add(methodResult);\n        methodResult.setParentResource(this);\n    }\n\n    public Set<String> getRequestMediaTypes() {\n        return requestMediaTypes;\n    }\n\n    public Set<String> getResponseMediaTypes() {\n        return responseMediaTypes;\n    }\n\n    public MethodResult getParentSubResourceLocator() {\n        return parentSubResourceLocator;\n    }\n\n    public void setParentSubResourceLocator(final MethodResult parentSubResourceLocator) {\n        this.parentSubResourceLocator = parentSubResourceLocator;\n    }\n\n    public boolean isDeprecated() {\n        return deprecated;\n    }\n\n    public void setDeprecated(boolean deprecated) {\n        this.deprecated = deprecated;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final ClassResult that = (ClassResult) o;\n\n        if (!requestMediaTypes.equals(that.requestMediaTypes)) return false;\n        if (applicationPath != null ? !applicationPath.equals(that.applicationPath) : that.applicationPath != null)\n            return false;\n        if (!classFields.equals(that.classFields)) return false;\n        if (!methods.equals(that.methods)) return false;\n        if (resourcePath != null ? !resourcePath.equals(that.resourcePath) : that.resourcePath != null) return false;\n        if (deprecated != that.deprecated) return false;\n        return responseMediaTypes.equals(that.responseMediaTypes);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = applicationPath != null ? applicationPath.hashCode() : 0;\n        result = 31 * result + (resourcePath != null ? resourcePath.hashCode() : 0);\n        result = 31 * result + classFields.hashCode();\n        result = 31 * result + methods.hashCode();\n        result = 31 * result + requestMediaTypes.hashCode();\n        result = 31 * result + responseMediaTypes.hashCode();\n        result = 31 * result + (deprecated ? 1231 : 1237);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"ClassResult{\" +\n                \"applicationPath='\" + applicationPath + '\\'' +\n                \", resourcePath='\" + resourcePath + '\\'' +\n                \", classFields=\" + classFields +\n                \", methods=\" + methods +\n                \", requestMediaTypes=\" + requestMediaTypes +\n                \", responseMediaTypes=\" + responseMediaTypes +\n                \", parentSubResourceLocator=\" + (parentSubResourceLocator == null ? \"null\" : \"notNull\") +\n                \", deprecated=\" + deprecated +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/model/results/MethodResult.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.model.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Represents a resource method result.\n *\n * @author Sebastian Daschner\n */\npublic class MethodResult {\n\n    private final Set<String> requestMediaTypes = new HashSet<>();\n    private final Set<String> responseMediaTypes = new HashSet<>();\n    private final Set<MethodParameter> methodParameters = new HashSet<>();\n    private final Set<HttpResponse> responses = new HashSet<>();\n    private final List<Instruction> instructions = new ArrayList<>();\n    private String path;\n    private String requestBodyType;\n    private MethodIdentifier originalMethodSignature;\n    private HttpMethod httpMethod;\n    private ClassResult subResource;\n    private ClassResult parentResource;\n    private MethodComment methodDoc;\n    private boolean deprecated;\n\n    public Set<String> getRequestMediaTypes() {\n        return requestMediaTypes;\n    }\n\n    public Set<String> getResponseMediaTypes() {\n        return responseMediaTypes;\n    }\n\n    public Set<MethodParameter> getMethodParameters() {\n        return methodParameters;\n    }\n\n    public Set<HttpResponse> getResponses() {\n        return responses;\n    }\n\n    public List<Instruction> getInstructions() {\n        return instructions;\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(final String path) {\n        this.path = path;\n    }\n\n    public String getRequestBodyType() {\n        return requestBodyType;\n    }\n\n    public void setRequestBodyType(final String requestBodyType) {\n        this.requestBodyType = requestBodyType;\n    }\n\n    public MethodIdentifier getOriginalMethodSignature() {\n        return originalMethodSignature;\n    }\n\n    public void setOriginalMethodSignature(MethodIdentifier originalMethodSignature) {\n        this.originalMethodSignature = originalMethodSignature;\n    }\n\n    public HttpMethod getHttpMethod() {\n        return httpMethod;\n    }\n\n    public void setHttpMethod(final HttpMethod httpMethod) {\n        this.httpMethod = httpMethod;\n    }\n\n    public ClassResult getSubResource() {\n        return subResource;\n    }\n\n    public void setSubResource(final ClassResult subResource) {\n        this.subResource = subResource;\n        subResource.setParentSubResourceLocator(this);\n    }\n\n    public ClassResult getParentResource() {\n        return parentResource;\n    }\n\n    public void setParentResource(final ClassResult parentResource) {\n        this.parentResource = parentResource;\n    }\n\n    public MethodComment getMethodDoc() {\n        return methodDoc;\n    }\n\n    public void setMethodDoc(final MethodComment methodDoc) {\n        this.methodDoc = methodDoc;\n    }\n\n    public boolean isDeprecated() {\n        return deprecated;\n    }\n\n    public void setDeprecated(boolean deprecated) {\n        this.deprecated = deprecated;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final MethodResult that = (MethodResult) o;\n\n        if (!requestMediaTypes.equals(that.requestMediaTypes)) return false;\n        if (!responseMediaTypes.equals(that.responseMediaTypes)) return false;\n        if (!methodParameters.equals(that.methodParameters)) return false;\n        if (!responses.equals(that.responses)) return false;\n        // TODO double-check\n//        if (!instructions.equals(that.instructions)) return false;\n        if (path != null ? !path.equals(that.path) : that.path != null) return false;\n        if (requestBodyType != null ? !requestBodyType.equals(that.requestBodyType) : that.requestBodyType != null)\n            return false;\n        if (httpMethod != that.httpMethod) return false;\n        if (subResource != null ? !subResource.equals(that.subResource) : that.subResource != null) return false;\n        if (methodDoc != null ? !methodDoc.equals(that.methodDoc) : that.methodDoc != null) return false;\n        if (deprecated != that.deprecated) return false;\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = requestMediaTypes.hashCode();\n        result = 31 * result + responseMediaTypes.hashCode();\n        result = 31 * result + methodParameters.hashCode();\n        result = 31 * result + responses.hashCode();\n//        result = 31 * result + instructions.hashCode();\n        result = 31 * result + (path != null ? path.hashCode() : 0);\n        result = 31 * result + (requestBodyType != null ? requestBodyType.hashCode() : 0);\n        result = 31 * result + (httpMethod != null ? httpMethod.hashCode() : 0);\n        result = 31 * result + (subResource != null ? subResource.hashCode() : 0);\n        result = 31 * result + (methodDoc != null ? methodDoc.hashCode() : 0);\n        result = 31 * result + (deprecated ? 1231 : 1237);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"MethodResult{\" +\n                \"requestMediaTypes=\" + requestMediaTypes +\n                \", responseMediaTypes=\" + responseMediaTypes +\n                \", methodParameters=\" + methodParameters +\n                \", responses=\" + responses +\n//                \", instructions=\" + instructions +\n                \", path='\" + path + '\\'' +\n                \", requestBodyType='\" + requestBodyType + '\\'' +\n                \", httpMethod=\" + httpMethod +\n                \", subResource=\" + subResource +\n                \", methodDoc=\" + methodDoc +\n                \", parentResource=\" + (parentResource == null ? \"null\" : \"notNull\") +\n                \", deprecated=\" + deprecated +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/utils/DebugUtils.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.utils;\n\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.stream.IntStream;\n\n/**\n * @author Sebastian Daschner\n */\npublic final class DebugUtils {\n\n    private static final char INDENTATION_CHARACTER = ' ';\n    private static final int INDENTATION_SIZE = 2;\n\n    private DebugUtils() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Prettifies the {@link Object#toString()} output generated by IntelliJ.\n     *\n     * @param object The object to print\n     * @return The toString representation with line breaks and indentations\n     */\n    public static String prettyToString(final Object object) {\n        return prettyToString(object, INDENTATION_SIZE);\n    }\n\n    /**\n     * Prettifies the {@link Object#toString()} output generated by IntelliJ.\n     *\n     * @param object      The object to print\n     * @param indentation The number of blanks on a new line\n     * @return The toString representation with line breaks and indentations\n     */\n    public static String prettyToString(final Object object, final int indentation) {\n        final String string = object.toString();\n\n        // position of new lines and number of intending spaces\n        final Map<Integer, Integer> newLines = new TreeMap<>();\n\n        int currentLevel = 0;\n        boolean inStringLiteral = false;\n        for (int i = 0; i < string.length(); i++) {\n            final char currentChar = string.charAt(i);\n            if (currentChar == ',' && !inStringLiteral)\n                newLines.put(i, currentLevel);\n            if (currentChar == '{' && !inStringLiteral)\n                currentLevel++;\n            if (currentChar == '}' && !inStringLiteral)\n                currentLevel--;\n\n            // known flaw -> will fail for string containing a ' character\n            if (currentChar == '\\'')\n                inStringLiteral = !inStringLiteral;\n        }\n\n        final StringBuilder builder = new StringBuilder(string);\n\n        int modifiedLength = 0;\n        for (final Map.Entry<Integer, Integer> entry : newLines.entrySet()) {\n            final String intend = IntStream.range(0, entry.getValue() * indentation).mapToObj(c -> INDENTATION_CHARACTER)\n                    .collect(() -> new StringBuilder(\"\\n\"), StringBuilder::append, StringBuilder::append).toString();\n\n            builder.insert(modifiedLength + entry.getKey() + 1, intend);\n            modifiedLength += intend.length();\n        }\n\n        return builder.toString();\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/utils/Pair.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.utils;\n\n/**\n * Represents a tuple of two elements.\n *\n * @param <T> The type of the left element\n * @param <U> The type of the right element\n * @author Sebastian Daschner\n */\npublic class Pair<T, U> {\n\n    private final T left;\n    private final U right;\n\n    private Pair(final T left, final U right) {\n        this.left = left;\n        this.right = right;\n    }\n\n    public T getLeft() {\n        return left;\n    }\n\n    public U getRight() {\n        return right;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        final Pair pair = (Pair) o;\n\n        if (left != null ? !left.equals(pair.left) : pair.left != null) return false;\n        return !(right != null ? !right.equals(pair.right) : pair.right != null);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = left != null ? left.hashCode() : 0;\n        result = 31 * result + (right != null ? right.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    public String toString() {\n        return \"Pair{\" +\n                \"left=\" + left +\n                \", right=\" + right +\n                '}';\n    }\n\n    /**\n     * Creates a new pair with left and right value.\n     *\n     * @param left  The left value (can be {@code null})\n     * @param right The right value (can be {@code null})\n     * @param <V>   The type of the left value\n     * @param <W>   The type of the right value\n     * @return The constructed pair\n     */\n    public static <V, W> Pair<V, W> of(final V left, final W right) {\n        return new Pair<>(left, right);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/sebastian_daschner/jaxrs_analyzer/utils/StringUtils.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.utils;\n\n/**\n * Contains utility functions for Strings.\n *\n * @author Sebastian Daschner\n */\npublic final class StringUtils {\n\n    private StringUtils() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Checks if the given String is not {@code null}, empty or consists solely of whitespaces.\n     *\n     * @param arg The String to check\n     * @throws java.lang.IllegalArgumentException If the String is invalid.\n     */\n    public static void requireNonBlank(final String arg) {\n        if (isBlank(arg))\n            throw new IllegalArgumentException(\"String argument is blank.\");\n    }\n\n    /**\n     * Checks if the given String is {@code null}, empty or consists solely of whitespaces.\n     *\n     * @param string The String to check\n     * @return {@code true} if the String is {@code null}, empty or whitespace\n     */\n    public static boolean isBlank(final String string) {\n        if (string == null || string.isEmpty())\n            return true;\n\n        return string.chars().allMatch(Character::isWhitespace);\n    }\n\n}\n"
  },
  {
    "path": "src/main/resources/META-INF/services/com.sebastian_daschner.jaxrs_analyzer.backend.Backend",
    "content": "com.sebastian_daschner.jaxrs_analyzer.backend.markdown.MarkdownBackend\ncom.sebastian_daschner.jaxrs_analyzer.backend.asciidoc.AsciiDocBackend\ncom.sebastian_daschner.jaxrs_analyzer.backend.plaintext.PlainTextBackend\ncom.sebastian_daschner.jaxrs_analyzer.backend.swagger.SwaggerBackend\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/MainTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.asciidoc.AsciiDocBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.plaintext.PlainTextBackend;\nimport com.sebastian_daschner.jaxrs_analyzer.backend.swagger.SwaggerBackend;\nimport org.junit.Test;\n\nimport java.util.Map;\n\nimport static org.hamcrest.CoreMatchers.instanceOf;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\npublic class MainTest {\n\n    @Test\n    public void shouldAddBinaryAttributes() {\n        final Map<String, String> conf = Main.addAttribute(\"att1 = val1\");\n        assertThat(conf.containsKey(\"att1\"), is(true));\n        assertThat(conf.get(\"att1\"), is(\"val1\"));\n    }\n\n    @Test\n    public void shouldAddSingleAttributes() {\n        final Map<String, String> conf = Main.addAttribute(\"att1\");\n        assertThat(conf.containsKey(\"att1\"), is(true));\n        assertThat(conf.get(\"att1\"), is(\"\"));\n    }\n\n    @Test\n    public void shouldAddEmptyAttributeValues() {\n        final Map<String, String> conf = Main.addAttribute(\"att1=\");\n        assertThat(conf.containsKey(\"att1\"), is(true));\n        assertThat(conf.get(\"att1\"), is(\"\"));\n    }\n\n    @Test\n    public void shouldLoadSwaggerFromJavaService() {\n        final Backend backend = JAXRSAnalyzer.constructBackend(\"swagger\");\n        assertThat(backend, is(instanceOf(SwaggerBackend.class)));\n    }\n\n    @Test\n    public void shouldLoadPlainTextFromJavaService() {\n        final Backend backend = JAXRSAnalyzer.constructBackend(\"plaintext\");\n        assertThat(backend, is(instanceOf(PlainTextBackend.class)));\n    }\n\n    @Test\n    public void shouldLoadAsciiDocFromJavaService() {\n        final Backend backend = JAXRSAnalyzer.constructBackend(\"asciidoc\");\n        assertThat(backend, is(instanceOf(AsciiDocBackend.class)));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/ProjectAnalyzerTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis;\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourceMethodBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.tools.JavaCompiler;\nimport javax.tools.JavaFileObject;\nimport javax.tools.StandardJavaFileManager;\nimport javax.tools.ToolProvider;\nimport java.io.File;\nimport java.net.MalformedURLException;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static java.util.Collections.singleton;\nimport static java.util.Collections.singletonList;\nimport static org.junit.Assert.*;\n\npublic class ProjectAnalyzerTest {\n\n    private ProjectAnalyzer classUnderTest;\n    private Path path;\n    private String ignoredRootResource = \"com.sebastian_daschner.jaxrs_test.IgnoredTestResources\";\n\n    @Before\n    public void setUp() throws MalformedURLException {\n        LogProvider.injectDebugLogger(System.out::println);\n\n        final String testClassPath = \"src/test/jaxrs-test\";\n\n        // invoke compilation for jaxrs-test classes\n        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();\n        final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);\n        final List<JavaFileObject> compilationUnits = findClassFiles(testClassPath, fileManager);\n\n        final JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, null, null, singletonList(\"-g\"), null, compilationUnits);\n        assertTrue(\"Could not compile test project\", compilationTask.call());\n\n        path = Paths.get(testClassPath).toAbsolutePath();\n\n        final Set<Path> classPaths = Stream.of(System.getProperty(\"java.class.path\").split(File.pathSeparator))\n                .map(Paths::get)\n                .collect(Collectors.toSet());\n\n        classPaths.add(path);\n        classUnderTest = new ProjectAnalyzer(classPaths);\n    }\n\n    @Test\n    public void test() {\n        final long startTime = System.currentTimeMillis();\n        final Resources actualResources = classUnderTest.analyze(singleton(path), singleton(path), singleton(ignoredRootResource));\n        System.out.println(\"Project analysis took \" + (System.currentTimeMillis() - startTime) + \" ms\");\n        final Resources expectedResources = getResources();\n\n        assertEquals(expectedResources.getBasePath(), actualResources.getBasePath());\n\n        assertFalse(actualResources.getResources().contains(\"ignored\"));\n        assertEquals(expectedResources.getResources(), actualResources.getResources());\n        assertResourceEquals(expectedResources, actualResources);\n        assertEquals(expectedResources.getTypeRepresentations().size(), actualResources.getTypeRepresentations().size());\n    }\n\n    private static void assertResourceEquals(final Resources expectedResources, final Resources actualResources) {\n        actualResources.getResources().forEach(r -> {\n            final Set<ResourceMethod> expectedMethods = expectedResources.getMethods(r);\n            final Set<ResourceMethod> actualMethods = actualResources.getMethods(r);\n            final String resourceText = \"Compared resource \" + r;\n\n            actualMethods.forEach(am -> {\n                final String methodText = resourceText + \", method \" + am.getMethod();\n                final ResourceMethod em = expectedMethods.stream().filter(m -> m.getMethod() == am.getMethod()).findAny()\n                        .orElseThrow(() -> new AssertionError(am.getMethod() + \" method not found for resource \" + r));\n                assertEquals(methodText, em.getMethodParameters(), am.getMethodParameters());\n                assertEquals(methodText, em.getRequestMediaTypes(), am.getRequestMediaTypes());\n                assertEquals(methodText, em.getResponseMediaTypes(), am.getResponseMediaTypes());\n                assertTypeIdentifierEquals(methodText, em.getRequestBody(), am.getRequestBody(), expectedResources.getTypeRepresentations(), actualResources.getTypeRepresentations());\n                assertEquals(methodText, em.getResponses().keySet(), am.getResponses().keySet());\n                assertEquals(methodText, em.getDescription(), am.getDescription());\n                assertEquals(methodText, em.getRequestBodyDescription(), am.getRequestBodyDescription());\n                am.getResponses().entrySet().forEach(ae -> {\n                    final Response ar = ae.getValue();\n                    final Response er = em.getResponses().get(ae.getKey());\n                    final String responseText = methodText + \", response \" + ae.getKey();\n                    assertEquals(responseText, er.getHeaders(), ar.getHeaders());\n                    assertTypeIdentifierEquals(responseText, er.getResponseBody(), ar.getResponseBody(), expectedResources.getTypeRepresentations(), actualResources.getTypeRepresentations());\n                });\n            });\n\n        });\n    }\n\n    private static void assertTypeIdentifierEquals(final String message, final TypeIdentifier expectedIdentifier, final TypeIdentifier actualIdentifier,\n                                                   final Map<TypeIdentifier, TypeRepresentation> expectedResources, final Map<TypeIdentifier, TypeRepresentation> actualResources) {\n        if (expectedIdentifier == null || actualIdentifier == null) {\n            assertNull(message, expectedIdentifier);\n            assertNull(message, actualIdentifier);\n            return;\n        }\n\n        if (!expectedIdentifier.getName().startsWith(\"$\")) {\n            assertEquals(message, expectedIdentifier, actualIdentifier);\n        }\n        assertRepresentationEquals(message, expectedResources.get(expectedIdentifier), actualResources.get(actualIdentifier), expectedResources, actualResources);\n    }\n\n    private static void assertRepresentationEquals(final String message, final TypeRepresentation expectedRepresentation, final TypeRepresentation actualRepresentation,\n                                                   final Map<TypeIdentifier, TypeRepresentation> expectedResources, final Map<TypeIdentifier, TypeRepresentation> actualResources) {\n        if (expectedRepresentation == null || actualRepresentation == null) {\n            assertNull(message, expectedRepresentation);\n            assertNull(message, actualRepresentation);\n            return;\n        }\n\n        assertEquals(expectedRepresentation.getClass(), actualRepresentation.getClass());\n        if (expectedRepresentation instanceof TypeRepresentation.CollectionTypeRepresentation) {\n            assertRepresentationEquals(message, ((TypeRepresentation.CollectionTypeRepresentation) expectedRepresentation).getRepresentation(),\n                    ((TypeRepresentation.CollectionTypeRepresentation) actualRepresentation).getRepresentation(), expectedResources, actualResources);\n        } else {\n            final Map<String, TypeIdentifier> expectedProperties = ((TypeRepresentation.ConcreteTypeRepresentation) expectedRepresentation).getProperties();\n            final Map<String, TypeIdentifier> actualProperties = ((TypeRepresentation.ConcreteTypeRepresentation) actualRepresentation).getProperties();\n            assertEquals(message, expectedProperties.keySet(), actualProperties.keySet());\n            actualProperties.forEach((k, v) -> assertTypeIdentifierEquals(message, expectedProperties.get(k), v, expectedResources, actualResources));\n        }\n    }\n\n    private static Resources getResources() {\n        final Resources resources = new Resources();\n        Map<String, TypeIdentifier> properties;\n\n        final TypeIdentifier stringIdentifier = TypeIdentifier.ofType(Types.STRING);\n\n        properties = new HashMap<>();\n        properties.put(\"id\", TypeIdentifier.ofType(Types.PRIMITIVE_LONG));\n        properties.put(\"name\", stringIdentifier);\n        final TypeIdentifier modelIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_test/Model;\");\n        final TypeRepresentation modelRepresentation = TypeRepresentation.ofConcrete(modelIdentifier, properties);\n        resources.getTypeRepresentations().put(modelIdentifier, modelRepresentation);\n\n        final TypeIdentifier modelListIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<+Lcom/sebastian_daschner/jaxrs_test/Model;>;\");\n        resources.getTypeRepresentations().put(modelListIdentifier, TypeRepresentation.ofCollection(modelListIdentifier, modelRepresentation));\n        final TypeIdentifier stringArrayListIdentifier = TypeIdentifier.ofType(\"Ljava/util/ArrayList<Ljava/lang/String;>;\");\n        resources.getTypeRepresentations().put(stringArrayListIdentifier, TypeRepresentation.ofCollection(stringArrayListIdentifier, TypeRepresentation.ofConcrete(stringIdentifier)));\n\n        resources.setBasePath(\"rest\");\n\n        // test\n        ResourceMethod firstGet = ResourceMethodBuilder.withMethod(HttpMethod.GET).andAcceptMediaTypes(\"application/json\")\n                .andResponseMediaTypes(\"application/json\").andResponse(200, ResponseBuilder\n                        .withResponseBody(modelListIdentifier).build()).build();\n        ResourceMethod firstPost = ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(Types.STRING)\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build();\n        ResourceMethod firstPut = ResourceMethodBuilder.withMethod(HttpMethod.PUT).andRequestBodyType(modelIdentifier)\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andResponse(202, ResponseBuilder.newBuilder().build()).build();\n        addMethods(resources, \"test\", firstGet, firstPost, firstPut);//, firstDelete);\n\n        // test/{foobar}\n        ResourceMethod firstDelete = ResourceMethodBuilder.withMethod(HttpMethod.DELETE, \"Deletes a test.\").andPathParam(\"foobar\", Types.STRING, null, \"The foo query\")\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andResponse(204, ResponseBuilder.newBuilder().build()).build();\n        addMethods(resources, \"test/{foobar}\", firstDelete);\n\n        // test/{id}\n        ResourceMethod secondGet = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(modelIdentifier).build())\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andPathParam(\"id\", Types.STRING).build();\n        ResourceMethod secondDelete = ResourceMethodBuilder.withMethod(HttpMethod.DELETE)\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andPathParam(\"id\", \"Ljava/lang/String;\")\n                .andResponse(204, ResponseBuilder.newBuilder().build())\n                .andResponse(404, ResponseBuilder.newBuilder().andHeaders(\"X-Message\").build())\n                .andResponse(500, ResponseBuilder.newBuilder().build()).build();\n        addMethods(resources, \"test/{id}\", secondGet, secondDelete);\n\n        // test/{id}/test\n        ResourceMethod thirdDelete = ResourceMethodBuilder.withMethod(HttpMethod.DELETE, \"Deletes another test.\")\n                .andAcceptMediaTypes(\"application/json\").andResponseMediaTypes(\"application/json\")\n                .andPathParam(\"id\", Types.STRING, null, \"The ID\").andQueryParam(\"query\", Types.PRIMITIVE_INT, null, \"The deletion query\")\n                .andResponse(204, ResponseBuilder.newBuilder().build()).build();\n        addMethods(resources, \"test/{id}/test\", thirdDelete);\n\n        // test/test\n        ResourceMethod fourthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Returns a test string with plain text.\").andAcceptMediaTypes(\"application/json\")\n                .andResponseMediaTypes(\"text/plain\", \"application/json\").andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"test/test\", fourthGet);\n        \n        // resourceWithoutClassLevelJavadoc/test\n        ResourceMethod getResourceWithoutJavadoc = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Returns a test string in json.\").andAcceptMediaTypes(\"application/json\")\n                .andResponseMediaTypes(\"application/json\").andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"resourceWithoutJavadoc/test\", getResourceWithoutJavadoc);\n\n        // complex\n        ResourceMethod eighthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponseMediaTypes(\"application/json\")\n                .andResponse(200, ResponseBuilder.withResponseBody(stringArrayListIdentifier).build()).build();\n        ResourceMethod secondPut = ResourceMethodBuilder.withMethod(HttpMethod.PUT)\n                .andResponse(204, ResponseBuilder.newBuilder().build()).build();\n        addMethods(resources, \"complex\", eighthGet, secondPut);\n\n        // complex/string\n        ResourceMethod ninthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponseMediaTypes(\"application/json\")\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/string\", ninthGet);\n\n        // complex/status\n        ResourceMethod fifthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/status\", fifthGet);\n\n        // complex/{info}\n        ResourceMethod sixthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andPathParam(\"info\", Types.STRING).andResponse(200, ResponseBuilder.newBuilder().andHeaders(\"X-Info\").build()).build();\n        addMethods(resources, \"complex/{info}\", sixthGet);\n\n        // complex/sub\n        ResourceMethod secondPost = ResourceMethodBuilder.withMethod(HttpMethod.POST, \"Creates a sub resource.\").andRequestBodyType(Types.STRING, \"The entity\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(202, ResponseBuilder.newBuilder().andHeaders(\"X-Info\").build()).build();\n        addMethods(resources, \"complex/sub\", secondPost);\n\n        // subsub\n        addMethods(resources, \"subsub\", secondPost);\n\n        // complex/sub/{name}\n        ResourceMethod seventhGet = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Gets a sub resource.\").andPathParam(\"name\", Types.STRING, null, \"The name\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/sub/{name}\", seventhGet);\n\n        // subsub/{name}\n        addMethods(resources, \"subsub/{name}\", seventhGet);\n\n        // complex/anotherSub\n        ResourceMethod thirdPost = ResourceMethodBuilder.withMethod(HttpMethod.POST, \"Creates a sub resource.\").andRequestBodyType(Types.STRING, \"The entity\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(202, ResponseBuilder.newBuilder().andHeaders(\"X-Info\").build()).build();\n        addMethods(resources, \"complex/anotherSub\", thirdPost);\n\n        // complex/anotherSub/{name}\n        ResourceMethod tenthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Gets a sub resource.\").andPathParam(\"name\", Types.STRING, null, \"The name\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/anotherSub/{name}\", tenthGet);\n\n        // complex/anotherSubres\n        ResourceMethod fourthPost = ResourceMethodBuilder.withMethod(HttpMethod.POST, \"Creates a sub resource.\").andRequestBodyType(Types.STRING, \"The entity\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(202, ResponseBuilder.newBuilder().andHeaders(\"X-Info\").build()).build();\n        addMethods(resources, \"complex/anotherSubres\", fourthPost);\n\n        // complex/anotherSubres/{name}\n        ResourceMethod eleventhGet = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Gets a sub resource.\").andPathParam(\"name\", Types.STRING, null, \"The name\")\n                .andQueryParam(\"query\", Types.STRING, null, \"The query param.\")\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/anotherSubres/{name}\", eleventhGet);\n\n        // complex/auth\n        ResourceMethod authGet = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Creates an authorization endpoint.\")\n                .andHeaderParam(\"Authorization\", Types.STRING)\n                .andResponse(200, ResponseBuilder.withResponseBody(stringIdentifier).build()).build();\n        addMethods(resources, \"complex/auth\", authGet);\n\n        // json_tests\n        final TypeIdentifier firstIdentifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        // All numbers are treat as double (JSON type number)\n        properties.put(\"duke\", TypeIdentifier.ofType(Types.DOUBLE));\n        resources.getTypeRepresentations().put(firstIdentifier, TypeRepresentation.ofConcrete(firstIdentifier, properties));\n        ResourceMethod twelfthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponse(200, ResponseBuilder.withResponseBody(firstIdentifier).build()).build();\n\n        final TypeIdentifier secondIdentifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        resources.getTypeRepresentations().put(secondIdentifier, TypeRepresentation.ofConcrete(secondIdentifier, properties));\n\n        // TODO type should be Object because JsonArray is interpreted as collection type\n        final TypeIdentifier thirdIdentifier = TypeIdentifier.ofDynamic();\n        resources.getTypeRepresentations().put(thirdIdentifier, TypeRepresentation.ofCollection(thirdIdentifier, TypeRepresentation.ofConcrete(stringIdentifier)));\n        ResourceMethod fifthPost = ResourceMethodBuilder.withMethod(HttpMethod.POST)\n                .andResponse(202, ResponseBuilder.withResponseBody(secondIdentifier).build())\n                .andResponse(500, ResponseBuilder.newBuilder().build())\n                .andResponse(200, ResponseBuilder.withResponseBody(thirdIdentifier).build()).build();\n\n        addMethods(resources, \"json_tests\", twelfthGet, fifthPost);\n\n        // json_tests/info\n        final TypeIdentifier fourthIdentifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"duke\", stringIdentifier);\n        properties.put(\"hello\", stringIdentifier);\n        resources.getTypeRepresentations().put(fourthIdentifier, TypeRepresentation.ofConcrete(fourthIdentifier, properties));\n        ResourceMethod thirteenthGet = ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponse(200, ResponseBuilder.withResponseBody(fourthIdentifier).build())\n                .build();\n        addMethods(resources, \"json_tests/info\", thirteenthGet);\n\n        return resources;\n    }\n\n    private static void addMethods(final Resources resources, final String path, final ResourceMethod... methods) {\n        Stream.of(methods).forEach(m -> resources.addMethod(path, m));\n    }\n\n    private static List<JavaFileObject> findClassFiles(final String classPath, final StandardJavaFileManager fileManager, final String... packages) {\n        final Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(Paths.get(classPath, packages).toFile().listFiles((dir, name) -> name.endsWith(\".java\")));\n        List<JavaFileObject> classFiles = new LinkedList<>();\n        fileObjects.forEach(classFiles::add);\n\n        Stream.of(Paths.get(classPath, packages).toFile().listFiles(File::isDirectory)).map(File::getName)\n                .map(n -> {\n                    final String[] packagesNames = Arrays.copyOf(packages, packages.length + 1);\n                    packagesNames[packages.length] = n;\n                    return packagesNames;\n                }).forEach(p -> classFiles.addAll(findClassFiles(classPath, fileManager, p)));\n\n        return classFiles;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/SubResourceLocatorMethodContentAnalyzerTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.JobRegistry;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ProjectMethodClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.AfterClass;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.mockito.ArgumentCaptor;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.Type;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Modifier;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils.getClasses;\nimport static org.junit.Assert.assertEquals;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Mockito.*;\n\n@RunWith(Parameterized.class)\npublic class SubResourceLocatorMethodContentAnalyzerTest {\n\n    private static JobRegistry originalJobRegistry;\n    private final SubResourceLocatorMethodContentAnalyzer classUnderTest;\n    private final String testClassSimpleName;\n    private final String testClassName;\n    private final Set<String> expectedClassNames;\n    private final JobRegistry jobRegistry;\n    private String signature;\n\n\n    public SubResourceLocatorMethodContentAnalyzerTest(final String testClassSimpleName, final String testClassName, final String signature, final Set<String> expectedClassNames)\n            throws ReflectiveOperationException {\n        this.testClassSimpleName = testClassSimpleName;\n        this.testClassName = testClassName;\n        this.signature = signature;\n        this.expectedClassNames = expectedClassNames;\n        jobRegistry = mock(JobRegistry.class);\n        this.classUnderTest = new SubResourceLocatorMethodContentAnalyzer();\n        injectJobRegistry(jobRegistry);\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource\");\n\n        for (final String testClass : testClasses) {\n            final Object[] testData = new Object[4];\n\n            final Class<?> loadedClass = JavaUtils.loadClassFromName(testClass);\n            testData[0] = testClass.substring(testClass.lastIndexOf('/') + 1);\n            testData[1] = testClass;\n            testData[2] = Type.getMethodDescriptor(loadedClass.getDeclaredMethod(\"method\"));\n            testData[3] = loadedClass.getDeclaredMethod(\"getResult\").invoke(null);\n\n            data.add(testData);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() throws IOException {\n        try {\n            final ClassReader classReader = new ContextClassReader(testClassName);\n\n            final MethodResult methodResult = new MethodResult();\n            final ClassResult parentResource = new ClassResult();\n            parentResource.setOriginalClass(testClassName);\n            methodResult.setParentResource(parentResource);\n            final ProjectMethodClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, MethodIdentifier.of(testClassName, \"method\", signature, false));\n            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n\n            classUnderTest.analyze(methodResult);\n        } catch (Exception e) {\n            System.err.println(\"failed for \" + testClassName);\n            throw e;\n        }\n\n        final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);\n        verify(jobRegistry, atLeastOnce()).analyzeResourceClass(captor.capture(), any());\n\n        assertEquals(\"failed for \" + testClassName, expectedClassNames, captor.getAllValues().stream().collect(Collectors.toSet()));\n        verify(jobRegistry, times(expectedClassNames.size())).analyzeResourceClass(any(), any());\n    }\n\n    @AfterClass\n    public static void tearDown() throws NoSuchFieldException, IllegalAccessException {\n        injectJobRegistry(originalJobRegistry);\n    }\n\n    private static void injectJobRegistry(final JobRegistry jobRegistry) throws NoSuchFieldException, IllegalAccessException {\n        final Field field = JobRegistry.class.getDeclaredField(\"INSTANCE\");\n        field.setAccessible(true);\n        originalJobRegistry = JobRegistry.getInstance();\n        Field modifiersField = Field.class.getDeclaredField(\"modifiers\");\n        modifiersField.setAccessible(true);\n        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);\n        field.set(null, jobRegistry);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/ByteCodeCollectorTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ProjectMethodClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.Type;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.lang.reflect.Method;\nimport java.util.*;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.of;\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(Parameterized.class)\npublic class ByteCodeCollectorTest {\n\n    private final String testClassSimpleName;\n    private final String testClass;\n    private final List<Instruction> expectedInstructions;\n\n    public ByteCodeCollectorTest(final String testClassSimpleName, final String testClass, final List<Instruction> expectedInstructions) {\n        this.testClassSimpleName = testClassSimpleName;\n        this.testClass = testClass;\n        this.expectedInstructions = expectedInstructions;\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = TestClassUtils.getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses\");\n\n        for (final String testClass : testClasses) {\n            final Object[] testData = new Object[3];\n\n            testData[0] = testClass.substring(testClass.lastIndexOf('/') + 1);\n            testData[1] = testClass;\n\n            // evaluate static \"getResult\"-method\n            testData[2] = JavaUtils.loadClassFromName(testClass).getDeclaredMethod(\"getResult\").invoke(null);\n\n            data.add(testData);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() throws IOException {\n        // round trip to find the correct test method\n        final Method method = Stream.of(JavaUtils.loadClassFromName(testClass).getDeclaredMethods()).filter(m -> m.getName().equals(\"method\")).findAny().orElseThrow(NoSuchElementException::new);\n\n        final ClassReader classReader = new ContextClassReader(testClass);\n        final MethodResult methodResult = new MethodResult();\n        final ProjectMethodClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, of(testClass, \"method\", Type.getMethodDescriptor(method), false));\n        classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n\n        final List<Instruction> actualInstructions = methodResult.getInstructions();\n\n        assertEquals(expectedInstructions, actualInstructions);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass1 {\n\n    public void method() {\n        int status = 200;\n        int anotherStatus = 100;\n        status = anotherStatus = 300;\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        instructions.add(new PushInstruction(200, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(1, Types.OBJECT, null));\n        instructions.add(new PushInstruction(100, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new PushInstruction(300, Types.PRIMITIVE_INT, null));\n        instructions.add(new DupInstruction(null));\n        instructions.add(new StoreInstruction(2, Types.PRIMITIVE_INT, \"anotherStatus\", null));\n        instructions.add(new StoreInstruction(1, Types.PRIMITIVE_INT, \"status\", null));\n        instructions.add(new DefaultInstruction(\"RETURN\", null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass2 {\n\n    public void method() {\n        int status = 200;\n        if ((status = 300) > 0) {\n            status = 100;\n        }\n        status = 200;\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        instructions.add(new PushInstruction(200, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(1, Types.OBJECT, null));\n        instructions.add(new PushInstruction(300, Types.PRIMITIVE_INT, null));\n        instructions.add(new DupInstruction(null));\n        instructions.add(new StoreInstruction(1, Types.PRIMITIVE_INT, \"status\", null));\n        instructions.add(new SizeChangingInstruction(\"IFLE\", 0, 1, null));\n        instructions.add(new PushInstruction(100, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(1, Types.PRIMITIVE_INT, \"status\", null));\n        instructions.add(new PushInstruction(200, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(1, Types.PRIMITIVE_INT, \"status\", null));\n        instructions.add(new DefaultInstruction(\"RETURN\", null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass3 {\n\n    public int method(final int number) {\n        try {\n            return 3 * 2 / number;\n        } catch (ArithmeticException e) {\n            e.printStackTrace();\n            return 0;\n        }\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new PushInstruction(6, Types.PRIMITIVE_INT, null));\n        instructions.add(new LoadInstruction(1, Types.PRIMITIVE_INT, \"number\", null, null));\n        instructions.add(new SizeChangingInstruction(\"IDIV\", 1, 2, null));\n        instructions.add(new ReturnInstruction(null));\n\n        instructions.add(new ExceptionHandlerInstruction(null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new LoadInstruction(2, \"Ljava/lang/ArithmeticException;\", \"e\", null, null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofNonStatic(\"java/lang/ArithmeticException\", \"printStackTrace\", Types.PRIMITIVE_VOID), null));\n        instructions.add(new PushInstruction(0, Types.PRIMITIVE_INT, null));\n        instructions.add(new ReturnInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass4 {\n\n    public int method(final int number) {\n        try {\n            return 3 * 2 / number;\n        } finally {\n            System.out.println(\"Computed\");\n        }\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new PushInstruction(6, Types.PRIMITIVE_INT, null));\n        instructions.add(new LoadInstruction(1, Types.PRIMITIVE_INT, \"number\", null, null));\n        instructions.add(new SizeChangingInstruction(\"IDIV\", 1, 2, null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new GetStaticInstruction(\"java/lang/System\", \"out\", \"Ljava/io/PrintStream;\", System.out, null));\n        instructions.add(new PushInstruction(\"Computed\", Types.STRING, null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofNonStatic(\"java/io/PrintStream\", \"println\", Types.PRIMITIVE_VOID, Types.STRING), null));\n        instructions.add(new LoadInstruction(2, Types.OBJECT, null, null));\n        instructions.add(new ReturnInstruction(null));\n\n        instructions.add(new ExceptionHandlerInstruction(null));\n        instructions.add(new StoreInstruction(3, Types.OBJECT, null));\n        instructions.add(new GetStaticInstruction(\"java/lang/System\", \"out\", \"Ljava/io/PrintStream;\", System.out, null));\n        instructions.add(new PushInstruction(\"Computed\", Types.STRING, null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofNonStatic(\"java/io/PrintStream\", \"println\", Types.PRIMITIVE_VOID, Types.STRING), null));\n        instructions.add(new LoadInstruction(3, Types.OBJECT, null, null));\n        instructions.add(new ThrowInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass5 {\n\n    public int method(final int number) {\n        synchronized (this) {\n            return 3 * 2 / number;\n        }\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new LoadInstruction(0, 'L' + TestClass5.class.getCanonicalName().replace('.', '/') + ';', \"this\", null, null));\n        instructions.add(new DupInstruction(null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new SizeChangingInstruction(\"MONITORENTER\", 0, 1, null));\n        instructions.add(new PushInstruction(6,Types.PRIMITIVE_INT, null));\n        instructions.add(new LoadInstruction(1, Types.PRIMITIVE_INT, \"number\", null, null));\n        instructions.add(new SizeChangingInstruction(\"IDIV\", 1, 2, null));\n        instructions.add(new LoadInstruction(2, Types.OBJECT, null, null));\n        instructions.add(new SizeChangingInstruction(\"MONITOREXIT\", 0, 1, null));\n        instructions.add(new ReturnInstruction(null));\n\n        instructions.add(new ExceptionHandlerInstruction(null));\n        instructions.add(new StoreInstruction(3, Types.OBJECT, null));\n        instructions.add(new LoadInstruction(2, Types.OBJECT, null, null));\n        instructions.add(new SizeChangingInstruction(\"MONITOREXIT\", 0, 1, null));\n        instructions.add(new LoadInstruction(3, Types.OBJECT, null, null));\n        instructions.add(new ThrowInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass6 {\n\n    public synchronized int method(final int number) {\n        return 3 * 2 / number;\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new PushInstruction(6, Types.PRIMITIVE_INT, null));\n        instructions.add(new LoadInstruction(1, Types.PRIMITIVE_INT, \"number\", null, null));\n        instructions.add(new SizeChangingInstruction(\"IDIV\", 1, 2, null));\n        instructions.add(new ReturnInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass7 {\n\n    public synchronized int method(final int number) {\n        // force wide opcode use\n        int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25,\n                i26, i27, i28, i29, i30, i31, i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49,\n                i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, i61, i62, i63, i64, i65, i66, i67, i68, i69, i70, i71, i72, i73,\n                i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86, i87, i88, i89, i90, i91, i92, i93, i94, i95, i96, i97,\n                i98, i99, i100, i101, i102, i103, i104, i105, i106, i107, i108, i109, i110, i111, i112, i113, i114, i115, i116, i117,\n                i118, i119, i120, i121, i122, i123, i124, i125, i126, i127, i128, i129, i130, i131, i132, i133, i134, i135, i136,\n                i137, i138, i139, i140, i141, i142, i143, i144, i145, i146, i147, i148, i149, i150, i151, i152, i153, i154, i155,\n                i156, i157, i158, i159, i160, i161, i162, i163, i164, i165, i166, i167, i168, i169, i170, i171, i172, i173, i174,\n                i175, i176, i177, i178, i179, i180, i181, i182, i183, i184, i185, i186, i187, i188, i189, i190, i191, i192, i193,\n                i194, i195, i196, i197, i198, i199, i200, i201, i202, i203, i204, i205, i206, i207, i208, i209, i210, i211, i212,\n                i213, i214, i215, i216, i217, i218, i219, i220, i221, i222, i223, i224, i225, i226, i227, i228, i229, i230, i231,\n                i232, i233, i234, i235, i236, i237, i238, i239, i240, i241, i242, i243, i244, i245, i246, i247, i248, i249, i250,\n                i251, i252, i253, i254, i255, i256, i257, i258, i259, i260, i261, i262, i263, i264, i265, i266, i267, i268, i269,\n                i270, i271, i272, i273, i274, i275, i276, i277, i278, i279, i280, i281, i282, i283, i284, i285, i286, i287, i288,\n                i289, i290, i291, i292, i293, i294, i295, i296, i297, i298, i299;\n\n        i299 = 20;\n\n        i299++;\n\n        return i299;\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new PushInstruction(20, Types.PRIMITIVE_INT, null));\n        instructions.add(new StoreInstruction(300, Types.OBJECT, null));\n        instructions.add(new DefaultInstruction(\"IINC\",null));\n        instructions.add(new LoadInstruction(300, Types.PRIMITIVE_INT, \"i299\", null, null));\n        instructions.add(new ReturnInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass8 {\n\n    public double method(final int number) {\n        // force dup2 opcode use\n        final double d1, d2;\n\n        d1 = d2 = 2.0;\n\n        return d1;\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new PushInstruction(2.0, Types.DOUBLE, null));\n        instructions.add(new DupInstruction(null));\n        instructions.add(new StoreInstruction(4, Types.OBJECT, null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new LoadInstruction(2, Types.PRIMITIVE_DOUBLE, \"d1\", null, null));\n        instructions.add(new ReturnInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/collection/testclasses/TestClass9.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.collection.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.GetStaticInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.InvokeInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.ReturnInstruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport javax.ws.rs.core.Response;\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass9 {\n\n    public Response method(final int number) {\n        return Response.status(Response.Status.BAD_REQUEST).build();\n    }\n\n    public static List<Instruction> getResult() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        // constant folding\n        instructions.add(new GetStaticInstruction(\"javax/ws/rs/core/Response$Status\", \"BAD_REQUEST\", Types.RESPONSE_STATUS, Response.Status.BAD_REQUEST, null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofStatic(Types.CLASS_RESPONSE, \"status\", Types.RESPONSE_BUILDER, Types.RESPONSE_STATUS), null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofNonStatic(Types.CLASS_RESPONSE_BUILDER, \"build\", Types.RESPONSE), null));\n        instructions.add(new ReturnInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/RelevantInstructionReducerTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ProjectMethodClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.Type;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.lang.reflect.Method;\nimport java.util.*;\nimport java.util.stream.Stream;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.of;\n\n@RunWith(Parameterized.class)\npublic class RelevantInstructionReducerTest {\n\n    private final RelevantInstructionReducer classUnderTest;\n    private final String testClass;\n    private final List<Instruction> expectedInstructions;\n\n    public RelevantInstructionReducerTest(final String testClass, final List<Instruction> expectedInstructions) {\n        this.testClass = testClass;\n        this.expectedInstructions = expectedInstructions;\n        this.classUnderTest = new RelevantInstructionReducer();\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = TestClassUtils.getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses\");\n\n        testClassLabel:\n        for (final String testClass : testClasses) {\n            final Object[] testData = new Object[2];\n            data.add(testData);\n\n            testData[0] = testClass;\n            final Class<?> loadedClass = JavaUtils.loadClassFromName(testClass);\n\n            // take \"instructions\"-method with higher priority\n            for (Method method : loadedClass.getDeclaredMethods()) {\n                if (\"instructions\".equals(method.getName())) {\n                    testData[1] = loadedClass.getDeclaredMethod(\"instructions\").invoke(null);\n                    continue testClassLabel;\n                }\n            }\n\n            // \"expected\"#-methods\n            testData[1] = new LinkedList<>();\n            Stream.of(loadedClass.getDeclaredMethods())\n                    .filter(m -> m.getName().startsWith(\"expected\")).sorted(Comparator.comparing(Method::getName))\n                    .map(RelevantInstructionReducerTest::getInstructions)\n                    .forEach(((List<Instruction>) testData[1])::addAll);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() throws IOException {\n        // round trip to find the correct test method\n        final Method method = Stream.of(JavaUtils.loadClassFromName(testClass).getDeclaredMethods()).filter(m -> m.getName().equals(\"method\")).findAny().orElseThrow(NoSuchElementException::new);\n\n        final List<Instruction> visitedInstructions = classUnderTest.reduceInstructions(getInstructions(method));\n\n        Assert.assertEquals(\"failed for \" + testClass, expectedInstructions, visitedInstructions);\n    }\n\n    private static List<Instruction> getInstructions(final Method method) {\n        try {\n            final String className = method.getDeclaringClass().getCanonicalName().replace('.', '/');\n            final MethodResult methodResult = new MethodResult();\n            final ProjectMethodClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, of(className, method.getName(), Type.getMethodDescriptor(method), false));\n            new ContextClassReader(className).accept(visitor, ClassReader.EXPAND_FRAMES);\n\n            return methodResult.getInstructions();\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass1 {\n\n    public Response method() {\n        System.out.println(\"Hello World\");\n        return Response.status(Response.Status.ACCEPTED).build();\n    }\n\n    public Response expected1() {\n        return Response.status(Response.Status.ACCEPTED).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass10.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\nimport java.util.function.Supplier;\n\npublic class TestClass10 {\n\n    public Response method() {\n        final Supplier<Response> responseSupplier = this::response;\n        return responseSupplier.get();\n    }\n\n    private Response response() {\n        final Response.ResponseBuilder builder = Response.ok();\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n    public Response expected1() {\n        final Supplier<Response> responseSupplier = this::response;\n        return responseSupplier.get();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass2 {\n\n    public Response method() {\n        if (\"\".equals(new Object())) {\n            return Response.status(Response.Status.OK).build();\n        }\n        System.out.println(\"Hello World\");\n        return Response.status(Response.Status.ACCEPTED).build();\n    }\n\n    public Response expected1() {\n        return Response.status(Response.Status.OK).build();\n    }\n\n    public Response expected2() {\n        return Response.status(Response.Status.ACCEPTED).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass3 {\n\n    public Response method() {\n        Response.Status status = Response.Status.ACCEPTED;\n        System.out.println(\"Hello World\");\n        if (\"\".equals(\"\")) {\n            status = Response.Status.OK;\n        }\n        System.out.println(\"World\");\n        return Response.status(status).build();\n    }\n\n    public Response expected1() {\n        Response.Status status = Response.Status.ACCEPTED;\n        status = Response.Status.OK;\n        return Response.status(status).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass4 {\n\n    public Response method() {\n        int status = 200;\n        System.out.println(status);\n        int anotherStatus = 100;\n        status = anotherStatus = 300;\n        return Response.status(status).entity(anotherStatus).build();\n    }\n\n    public Response expected1() {\n        int status = 200;\n        System.out.println(status);\n        int anotherStatus = 100;\n        status = anotherStatus = 300;\n        return Response.status(status).entity(anotherStatus).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass5 {\n\n    public Response method() {\n        int status = 200;\n        if ((status = 300) > 0) {\n            status = 100;\n        }\n        return Response.status(status).build();\n    }\n\n    public Response expected1() {\n        int status = 200;\n        if ((status = 300) > 0) {\n            status = 100;\n        }\n        return Response.status(status).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\n\nimport javax.ws.rs.core.Response;\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class TestClass6 {\n\n    public Response method(final int number) {\n        synchronized (this) {\n            return Response.status(3 * 2 / number).build();\n        }\n    }\n\n    public static List<Instruction> instructions() {\n        final List<Instruction> instructions = new LinkedList<>();\n\n        instructions.add(new LoadInstruction(0, 'L' + TestClass6.class.getCanonicalName().replace('.', '/') + ';', \"this\", null, null));\n        instructions.add(new DupInstruction(null));\n        instructions.add(new StoreInstruction(2, Types.OBJECT, null));\n        instructions.add(new SizeChangingInstruction(\"MONITORENTER\", 0, 1, null));\n        instructions.add(new LoadInstruction(2, Types.OBJECT, null, null));\n        instructions.add(new SizeChangingInstruction(\"MONITOREXIT\", 0, 1, null));\n        instructions.add(new ExceptionHandlerInstruction(null));\n        instructions.add(new StoreInstruction(3, Types.OBJECT, null));\n        instructions.add(new PushInstruction(6, Types.PRIMITIVE_INT, null));\n        instructions.add(new LoadInstruction(1, Types.PRIMITIVE_INT, \"number\", null, null));\n        instructions.add(new SizeChangingInstruction(\"IDIV\", 1, 2, null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofStatic(Types.CLASS_RESPONSE, \"status\", Types.RESPONSE_BUILDER, Types.PRIMITIVE_INT), null));\n        instructions.add(new InvokeInstruction(MethodIdentifier.ofNonStatic(Types.CLASS_RESPONSE_BUILDER, \"build\", Types.RESPONSE), null));\n        instructions.add(new LoadInstruction(2, Types.OBJECT, null, null));\n        instructions.add(new SizeChangingInstruction(\"MONITOREXIT\", 0, 1, null));\n        instructions.add(new ReturnInstruction(null));\n        instructions.add(new LoadInstruction(3, Types.OBJECT, null, null));\n        instructions.add(new ThrowInstruction(null));\n\n        return instructions;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass7 {\n\n    public Response method() {\n        Response.ResponseBuilder builder = Response.ok();\n        if (otherMethod()) {\n            builder.header(\"X-Test\", \"Hello World\");\n        }\n        System.out.println(\"Test\");\n        return builder.build();\n    }\n\n    private boolean otherMethod() {\n        return true;\n    }\n\n    public Response expected1() {\n        Response.ResponseBuilder builder = Response.ok();\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\n\npublic class TestClass8 {\n\n    public Response method() {\n        Response.ResponseBuilder builder = Response.ok();\n        if (otherMethod()) {\n            builder.header(\"X-Test\", \"Hello World\");\n        }\n        System.out.println(\"Test\");\n        return builder.build();\n    }\n\n    private boolean otherMethod() {\n        return true;\n    }\n\n    public Response expected1() {\n        Response.ResponseBuilder builder = Response.ok();\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses/TestClass9.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction.testclasses;\n\nimport javax.ws.rs.core.Response;\nimport java.util.function.Supplier;\n\npublic class TestClass9 {\n\n    public Response method() {\n        final Supplier<Response> responseSupplier = () -> {\n            Response.ResponseBuilder builder = Response.ok();\n            builder.header(\"X-Test\", \"Hello World\");\n            return builder.build();\n        };\n        return responseSupplier.get();\n    }\n\n    public Response expected1() {\n        final Supplier<Response> responseSupplier = () -> {\n            Response.ResponseBuilder builder = Response.ok();\n            builder.header(\"X-Test\", \"Hello World\");\n            return builder.build();\n        };\n        return responseSupplier.get();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass1.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.subresource;\n\nimport javax.ws.rs.container.ResourceContext;\nimport java.util.Set;\n\nimport static java.util.Collections.singleton;\n\npublic class TestClass1 {\n\n    public SubResource method() {\n        ResourceContext rc = null;\n        return rc.getResource(SubResource.class);\n    }\n\n    public static Set<String> getResult() {\n        return singleton(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass1$SubResource\");\n    }\n\n    private class SubResource {\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass2.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.subresource;\n\nimport javax.ws.rs.container.ResourceContext;\nimport java.util.Set;\n\nimport static java.util.Collections.singleton;\n\npublic class TestClass2 {\n\n    public Object method() {\n        ResourceContext rc = null;\n        return rc.getResource(SubResource.class);\n    }\n\n    public static Set<String> getResult() {\n        return singleton(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass2$SubResource\");\n    }\n\n    private class SubResource {\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass3.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.subresource;\n\nimport javax.ws.rs.container.ResourceContext;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static java.util.Collections.singletonList;\n\npublic class TestClass3 {\n\n    public Object method() {\n        ResourceContext rc = null;\n        final Object resource = rc.getResource(SubResource.class);\n        return resource;\n    }\n\n    public static Set<String> getResult() {\n        return new HashSet<>(singletonList(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass3$SubResource\"));\n    }\n\n    private class SubResource {\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass4.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.subresource;\n\nimport javax.ws.rs.container.ResourceContext;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass4 {\n\n    private ResourceContext rc;\n\n    public Object method() {\n        return rc.initResource(new SubResource());\n    }\n\n    public static Set<String> getResult() {\n        return Collections.singleton(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass4$SubResource\");\n    }\n\n    private class SubResource {\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass5.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.subresource;\n\nimport javax.ws.rs.container.ResourceContext;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static java.util.Collections.singleton;\n\npublic class TestClass5 {\n\n    public Object method() {\n        ResourceContext rc = null;\n        if (\"\".equals(\"\"))\n            return rc.getResource(AnotherSubResource.class);\n        return rc.getResource(SubResource.class);\n    }\n\n    public static Set<String> getResult() {\n        // FEATURE test several resources\n//        return new HashSet<>(Arrays.asList(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass5$SubResource\",\n//                \"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass5$AnotherSubResource\"));\n        return new HashSet<>(singleton(\"com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/subresource/TestClass5$SubResource\"));\n    }\n\n    private class SubResource {\n    }\n\n    private class AnotherSubResource {\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/JAXRSMethodVisitorTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.Opcodes;\n\nimport java.util.List;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\npublic class JAXRSMethodVisitorTest {\n\n    private JAXRSMethodVisitor cut;\n    private ClassResult classResult;\n\n    @Before\n    public void setUp() {\n        classResult = new ClassResult();\n        final MethodIdentifier identifier = MethodIdentifier.of(\"Foobar\", \"foo\", \"()V\", false);\n        cut = new JAXRSMethodVisitor(identifier, classResult, new MethodResult(), true);\n    }\n\n    @Test\n    public void test() {\n        final Label start = new Label();\n        final Label end = new Label();\n\n        cut.visitLabel(new Label());\n        cut.visitIntInsn(Opcodes.BIPUSH, 2);\n        cut.visitLabel(start);\n        cut.visitVarInsn(Opcodes.ISTORE, 1);\n        cut.visitInsn(Opcodes.NOP);\n        cut.visitLabel(new Label());\n        cut.visitVarInsn(Opcodes.ILOAD, 1);\n        cut.visitLabel(end);\n\n        final List<Instruction> instructions = classResult.getMethods().iterator().next().getInstructions();\n        assertThat(instructions.size(), is(4));\n\n        cut.visitLocalVariable(\"foobar\", \"Ljava/lang/String;\", null, start, end, 1);\n\n        assertThat(instructions.size(), is(4));\n        assertThat(instructions.stream().filter(i -> i.getType() == Instruction.InstructionType.LOAD).count(), is(1L));\n        assertThat(instructions.stream().filter(i -> i.getType() == Instruction.InstructionType.STORE).count(), is(1L));\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/ResourceMethodContentAnalyzerTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes;\n\n\nimport com.sebastian_daschner.jaxrs_analyzer.LogProvider;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.BytecodeAnalyzer;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils.getClasses;\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(Parameterized.class)\npublic class ResourceMethodContentAnalyzerTest {\n\n    private final String testClassSimpleName;\n    private final String testClassName;\n    private final Set<HttpResponse> expectedResult;\n\n    @BeforeClass\n    public static void setUpLogger() {\n        LogProvider.injectDebugLogger(System.out::println);\n    }\n\n    public ResourceMethodContentAnalyzerTest(final String testClassSimpleName, final String testClassName, final Set<HttpResponse> expectedResult) {\n        this.testClassSimpleName = testClassSimpleName;\n        this.testClassName = testClassName;\n        this.expectedResult = expectedResult;\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response\");\n        testClasses.addAll(getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json\"));\n        testClasses.addAll(getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object\"));\n\n        for (final String testClass : testClasses) {\n            if (!testClass.contains(\"/TestClass\"))\n                continue;\n\n            final Object[] testData = new Object[3];\n\n            testData[0] = testClass.substring(testClass.lastIndexOf('/') + 1);\n            testData[1] = testClass;\n            testData[2] = JavaUtils.loadClassFromName(testClass).getDeclaredMethod(\"getResult\").invoke(null);\n\n            data.add(testData);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() throws IOException {\n        try {\n            final ClassReader classReader = new ContextClassReader(testClassName);\n            final ClassResult classResult = new ClassResult();\n\n            // only hook up to desired method\n            final ClassVisitor visitor = new JAXRSClassVisitor(classResult) {\n                @Override\n                public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {\n                    final MethodIdentifier identifier = MethodIdentifier.of(classResult.getOriginalClass(), name, signature == null ? desc : signature, false);\n                    if (\"method\".equals(name))\n                        return new JAXRSMethodVisitor(identifier, classResult, new MethodResult(), true);\n                    return null;\n                }\n            };\n\n            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n            new BytecodeAnalyzer().analyzeBytecode(classResult);\n\n            final Set<HttpResponse> actualResult = classResult.getMethods().iterator().next().getResponses();\n\n            assertEquals(testClassName, expectedResult, actualResult);\n        } catch (Exception e) {\n            System.err.println(\"exception in \" + testClassName);\n            throw e;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.JSON_OBJECT;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.STRING;\n\npublic class TestClass1 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        return Json.createObjectBuilder().add(\"key\", \"value\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(STRING, \"value\"));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass10.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass10 {\n\n    private Converter converter;\n\n    @javax.ws.rs.GET public javax.json.JsonArray method() {\n        JsonArrayBuilder builder = Json.createArrayBuilder();\n        final List<String> names = new LinkedList<>();\n        names.stream().map(converter::convert).forEach(builder::add);\n        return builder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(Types.STRING));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(Types.JSON_ARRAY);\n        httpResponse.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(httpResponse);\n    }\n\n    private interface Converter {\n        String convert(String string);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.json.JsonObjectBuilder;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.JSON_OBJECT;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.STRING;\n\npublic class TestClass2 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        final JsonObjectBuilder objectBuilder = Json.createObjectBuilder();\n        objectBuilder.add(\"key\", \"value\");\n        if (\"\".equals(\"\"))\n            objectBuilder.add(\"another\", \"value\");\n        else\n            objectBuilder.add(\"key\", \"test\");\n        return objectBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(STRING, \"value\", \"test\"));\n        jsonObject.getStructure().put(\"another\", new Element(STRING, \"value\"));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.json.JsonObjectBuilder;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass3 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        final JsonObjectBuilder objectBuilder = Json.createObjectBuilder();\n        objectBuilder.addNull(\"key\");\n        if (\"\".equals(\"\"))\n            objectBuilder.add(\"key\", \"test\");\n        objectBuilder.add(\"object\", Json.createObjectBuilder().add(\"duke\", 42).build());\n        return objectBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(new HashSet<>(Arrays.asList(STRING, OBJECT)), null, \"test\"));\n\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject innerObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        innerObject.getStructure().put(\"duke\", new Element(INTEGER, 42));\n        jsonObject.getStructure().put(\"object\", new Element(JSON_OBJECT, innerObject));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.json.JsonObjectBuilder;\nimport javax.json.JsonValue;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass4 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        final JsonObjectBuilder objectBuilder = Json.createObjectBuilder();\n        objectBuilder.addNull(\"key\");\n        if (\"\".equals(\"\"))\n            objectBuilder.add(\"value\", JsonValue.FALSE);\n        objectBuilder.add(\"test\", JsonValue.NULL);\n        objectBuilder.add(\"test\", JsonValue.TRUE);\n        return objectBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(OBJECT, null));\n        jsonObject.getStructure().put(\"value\", new Element(JSON_VALUE, JsonValue.FALSE));\n        jsonObject.getStructure().put(\"test\", new Element(JSON_VALUE, JsonValue.NULL, JsonValue.TRUE));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.json.JsonObjectBuilder;\nimport javax.json.JsonValue;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass5 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        final JsonObject object = Json.createObjectBuilder().add(\"test\", true).build();\n        final JsonObjectBuilder objectBuilder = Json.createObjectBuilder();\n        objectBuilder.addNull(\"key\");\n        if (\"\".equals(\"\"))\n            objectBuilder.add(\"value\", JsonValue.FALSE);\n        objectBuilder.add(\"test\", object.getBoolean(\"test\"));\n        return objectBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(OBJECT, null));\n        jsonObject.getStructure().put(\"value\", new Element(JSON_VALUE, JsonValue.FALSE));\n        jsonObject.getStructure().put(\"test\", new Element(PRIMITIVE_BOOLEAN, 1));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.json.Json;\nimport javax.json.JsonArray;\nimport javax.json.JsonObject;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass6 {\n\n    @javax.ws.rs.GET\n    public JsonObject method() {\n        final JsonArray array = Json.createArrayBuilder().add(true).add(\"duke\").build();\n        return Json.createObjectBuilder()\n                .add(\"array\", array)\n                .add(\"int\", 42)\n                .add(\"boolean\", true)\n                .add(\"long\", 100000000000000L)\n                .add(\"double\", 1.2d)\n                .add(\"jsonObject\", Json.createObjectBuilder().add(\"key\", \"value\").add(\"test\", 1).build())\n                .add(\"jsonArray\", Json.createArrayBuilder().add(\"first\").add(\"second\").add(3d)\n                        .add(Json.createObjectBuilder().add(\"key\", \"object\").build())\n                        .add(Json.createObjectBuilder().add(\"nested\", \"object\")))\n                .build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray jsonArray = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray();\n        jsonArray.getElements().add(new Element(PRIMITIVE_BOOLEAN, 1));\n        jsonArray.getElements().add(new Element(STRING, \"duke\"));\n        jsonObject.getStructure().put(\"array\", new Element(JSON_ARRAY, jsonArray));\n        jsonObject.getStructure().put(\"int\", new Element(INTEGER, 42));\n        jsonObject.getStructure().put(\"boolean\", new Element(PRIMITIVE_BOOLEAN, 1));\n        jsonObject.getStructure().put(\"long\", new Element(LONG, 100000000000000L));\n        jsonObject.getStructure().put(\"double\", new Element(DOUBLE, 1.2d));\n\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject object = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        object.getStructure().put(\"key\", new Element(STRING, \"value\"));\n        object.getStructure().put(\"test\", new Element(INTEGER, 1));\n        jsonObject.getStructure().put(\"jsonObject\", new Element(JSON_OBJECT, object));\n\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray array = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray();\n        array.getElements().add(new Element(STRING, \"first\"));\n        array.getElements().add(new Element(STRING, \"second\"));\n        array.getElements().add(new Element(DOUBLE, 3d));\n\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject firstNested = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        firstNested.getStructure().put(\"key\", new Element(STRING, \"object\"));\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject secondNested = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        secondNested.getStructure().put(\"nested\", new Element(STRING, \"object\"));\n\n        array.getElements().add(new Element(JSON_OBJECT, firstNested));\n        array.getElements().add(new Element(JSON_OBJECT, secondNested));\n        jsonObject.getStructure().put(\"jsonArray\", new Element(JSON_ARRAY, array));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(JSON_OBJECT);\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.json.JsonStructure;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass7 {\n\n    @javax.ws.rs.GET\n    public JsonStructure method() {\n        if (\"\".equals(\"\"))\n            return Json.createArrayBuilder().add(true).add(\"duke\").build();\n\n        return Json.createObjectBuilder().add(\"key\", \"value\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n\n        final JsonObject jsonObject = new JsonObject();\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(Types.PRIMITIVE_BOOLEAN, 1));\n        jsonArray.getElements().add(new Element(Types.STRING, \"duke\"));\n        jsonObject.getStructure().put(\"key\", new Element(Types.STRING, \"value\"));\n\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(\"Ljavax/json/JsonStructure;\");\n        httpResponse.getInlineEntities().add(jsonObject);\n        httpResponse.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.json.JsonStructure;\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass8 {\n\n    @javax.ws.rs.GET\n    public JsonStructure method() {\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);\n\n        return Json.createObjectBuilder().add(\"key\", \"value\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n\n        final JsonObject jsonObject = new JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(Types.STRING, \"value\"));\n\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(\"Ljavax/json/JsonStructure;\");\n        httpResponse.getInlineEntities().add(jsonObject);\n\n        final HttpResponse errorResponse = new HttpResponse();\n        errorResponse.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(httpResponse, errorResponse));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/json/TestClass9.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.json;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass9 {\n\n    @javax.ws.rs.GET public javax.json.JsonArray method() {\n        JsonArrayBuilder builder = Json.createArrayBuilder();\n        stateMachineNames().forEach(builder::add);\n        return builder.build();\n    }\n\n    private List<String> stateMachineNames() {\n        return Collections.emptyList();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(Types.STRING));\n\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(Types.JSON_ARRAY);\n        httpResponse.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(httpResponse);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass1.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass1 {\n\n    @javax.ws.rs.GET\n    public String method() {\n        return \"Hello World!\";\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(Types.STRING);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass10.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.time.Instant;\nimport java.time.LocalDate;\nimport java.time.ZoneId;\nimport java.util.*;\n\npublic class TestClass10 {\n\n    @javax.ws.rs.GET public String method() {\n        final StringBuilder builder = new StringBuilder();\n\n        getDailyAccesses().entrySet().stream()\n                .sorted(Comparator.comparing(Map.Entry::getKey))\n                .forEach(e -> {\n                    builder.append(e.getKey()).append(\":\\n\");\n                    e.getValue().entrySet().stream()\n                            .sorted(Comparator.comparing(Map.Entry::getKey))\n                            .forEach(a -> builder.append(a.getKey()).append(\": \").append(a.getValue()).append('\\n'));\n                    builder.append('\\n');\n                });\n\n        return builder.toString();\n    }\n\n    private Map<String, Map<LocalDate, Integer>> getDailyAccesses() {\n        return getAll().entrySet().stream().collect(HashMap::new, (m, e) -> m.put(e.getKey(), calculateDailyAccesses(e.getValue())), Map::putAll);\n    }\n\n    public Map<String, Set<Instant>> getAll() {\n        return Collections.emptyMap();\n    }\n\n    private Map<LocalDate, Integer> calculateDailyAccesses(final Set<Instant> timestamps) {\n        return timestamps.stream()\n                .map(t -> t.atZone(ZoneId.systemDefault()).toLocalDate())\n                .collect(HashMap::new, (m, d) -> m.merge(d, 1, (oldV, newV) -> oldV + newV), Map::putAll);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.singleton(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass11.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass11 {\n\n    @javax.ws.rs.GET public String method() {\n        final String service = getInstance(String.class);\n        return \"hello \" + service;\n    }\n\n    public <T> T getInstance(final Class<T> clazz) {\n        return (T) new Object();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.singleton(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass12.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass12<T> {\n\n    private T object;\n\n    @javax.ws.rs.GET public String method(final T body) {\n        final T object = this.object;\n        return \"hello \" + object + \", \" + body.toString();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.singleton(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass13.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass13 {\n\n    private TestManager<String> manager;\n\n    @javax.ws.rs.GET public String method() {\n        final String test = manager.getTest();\n        System.out.println(test.length());\n        return test;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.singleton(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build());\n    }\n\n    private static class TestManager<T> {\n\n        private T object;\n\n        public T getTest() {\n//            final T object = this.object;\n            System.out.println(object);\n            return object;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass14.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass14<T> {\n\n    private TestManager<String> manager;\n\n    @javax.ws.rs.GET public String method(final T body) {\n        final String test = manager.getTest(body);\n        System.out.println(test.length());\n        return test;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.singleton(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build());\n    }\n\n    private static class TestManager<T> {\n\n        private T object;\n\n        public <U> T getTest(final U object) {\n            final U otherObject = object;\n            final T thisObject = this.object;\n            System.out.println(otherObject);\n            System.out.println(thisObject);\n            return thisObject;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass2.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass2 {\n\n    @javax.ws.rs.GET\n    public String method() {\n        if (\"\".equals(\"\"))\n            return \"Hi World!\";\n        return \"Hello World!\";\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(Types.STRING);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass3.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass3 {\n\n    @javax.ws.rs.GET public List<String> method() {\n        if (\"\".equals(\"\"))\n            return Arrays.asList(\"Hi World!\");\n        return Collections.singletonList(\"Hello World!\");\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(\"Ljava/util/List<Ljava/lang/String;>;\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass4.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass4 {\n\n    @javax.ws.rs.GET\n    public Model method() {\n        if (\"\".equals(\"\"))\n            return new Model(\"hi\");\n        return new Model(\"Hello World!\");\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass4$Model;\");\n\n        return Collections.singleton(result);\n    }\n\n    private class Model {\n        public Model(final String string) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass5.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass5 {\n\n    @javax.ws.rs.GET public List<Model> method() {\n        if (\"\".equals(\"\"))\n            return Arrays.asList(new Model(\"hi\"));\n        return Collections.singletonList(new Model(\"Hello World!\"));\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass5$Model;>;\");\n\n        return Collections.singleton(result);\n    }\n\n    private class Model {\n        public Model(final String string) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass6.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.*;\n\npublic class TestClass6 {\n\n    @javax.ws.rs.GET public List<Model> method() {\n        if (\"\".equals(\"\"))\n            return new ArrayList<>();\n        return new LinkedList<>();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n        result.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass6$Model;>;\");\n\n        return Collections.singleton(result);\n    }\n\n    private class Model {\n        public Model(final String string) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass7.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass7 {\n\n    @javax.ws.rs.GET public List<Model> method() {\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(Response.Status.NOT_FOUND);\n        return new LinkedList<>();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass7$Model;>;\");\n\n        final HttpResponse notFoundResponse = new HttpResponse();\n        notFoundResponse.getStatuses().add(404);\n\n        return new HashSet<>(Arrays.asList(httpResponse, notFoundResponse));\n    }\n\n    private class Model {\n        public Model(final String string) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass8.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass8 {\n\n    @javax.ws.rs.GET public List<Model> method() {\n        if (\"\".equals(\"\"))\n            return handleResponse();\n        return new LinkedList<>();\n    }\n\n    private List<Model> handleResponse() {\n        throw new WebApplicationException(Response.Status.NOT_FOUND);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse httpResponse = new HttpResponse();\n        httpResponse.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass8$Model;>;\");\n\n        final HttpResponse notFoundResponse = new HttpResponse();\n        notFoundResponse.getStatuses().add(404);\n\n        return new HashSet<>(Arrays.asList(httpResponse, notFoundResponse));\n    }\n\n    private class Model {\n        public Model(final String string) {\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/object/TestClass9.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.object;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass9 {\n\n    @javax.ws.rs.GET public void method() {\n        if (\"\".equals(\"\"))\n            System.out.println(\"do something\");\n    }\n\n    public static Set<HttpResponse> getResult() {\n        return Collections.emptySet();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass1 {\n\n    @javax.ws.rs.GET public Response method() {\n        int status = 200;\n        int anotherStatus = 100;\n        status = anotherStatus = 300;\n        return Response.status(anotherStatus).entity(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getEntityTypes().add(Types.INTEGER);\n        result.getStatuses().addAll(Arrays.asList(100, 300));\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass10.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass10 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final int status = 400 + id.length();\n        return Response.status(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass11.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.GenericEntity;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass11 {\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<String> strings = new LinkedList<>();\n        strings.add(\"test\");\n        GenericEntity<List<String>> genericEntity = new GenericEntity<>(strings, List.class);\n        return Response.ok(genericEntity).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(\"Ljavax/ws/rs/core/GenericEntity<Ljava/util/List<Ljava/lang/String;>;>;\");\n        result.getEntityTypes().add(\"Ljavax/ws/rs/core/GenericEntity;\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass12.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass12 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final int status = getStatus();\n        return Response.status(status).build();\n    }\n\n    private int getStatus() {\n        if (\"\".equals(\"\"))\n            return 200;\n        return 201;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(Arrays.asList(200, 201));\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass13.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass13 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final int status = getStatus();\n\n        if (\"\".equals(\"\"))\n            throw new IllegalArgumentException(String.valueOf(status));\n\n        return Response.status(status).build();\n    }\n\n    private int getStatus() {\n        return 201;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(201);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass14.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass14 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final int status = getStatus();\n\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(String.valueOf(status), Response.Status.BAD_REQUEST);\n\n        return Response.status(status).build();\n    }\n\n    private int getStatus() {\n        return 201;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResponse = new HttpResponse();\n        firstResponse.getStatuses().add(201);\n\n        final HttpResponse secondResponse = new HttpResponse();\n        secondResponse.getStatuses().add(400);\n\n        return new HashSet<>(Arrays.asList(firstResponse, secondResponse));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass15.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * @author Sebastian Daschner\n */\n\npublic class TestClass15 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        if (\"\".equals(\"\")) {\n            return createResponse(Response.Status.NOT_FOUND);\n        }\n        return createResponse(Response.Status.OK);\n    }\n\n    private Response createResponse(final Response.Status status) {\n        return Response.status(status).header(\"X-Header\", \"Hello World\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(200);\n        firstResult.getHeaders().add(\"X-Header\");\n\n        secondResult.getStatuses().add(404);\n        secondResult.getHeaders().add(\"X-Header\");\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass16.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\n/**\n * @author Sebastian Daschner\n */\n\npublic class TestClass16 {\n\n    public TestClass16(final String test) {\n        System.out.println(test);\n    }\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final Response.Status status = Response.Status.OK;\n        new TestClass16(status.getReasonPhrase());\n        return Response.status(status).header(\"X-Header\", \"Hello World\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass17.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Set;\n\nimport static java.util.Arrays.asList;\nimport static java.util.Collections.singleton;\nimport static java.util.Collections.singletonList;\n\npublic class TestClass17 {\n\n    // test not particularly useful; only testing array type support\n    @javax.ws.rs.GET\n    public Response method() {\n        String[] strings = new String[2];\n        strings[0] = \"test\";\n        return Response.ok(strings).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(singletonList(200));\n        result.getEntityTypes().addAll(asList(\"[Ljava/lang/String;\", Types.OBJECT));\n\n        return singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass18.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.GenericEntity;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass18 {\n\n    // test not particularly useful; only testing generic map support\n    @javax.ws.rs.GET public Response method() {\n        final Map<String, String> map = new HashMap<>();\n        map.put(\"key\", \"value\");\n        GenericEntity<Map<String, String>> genericEntity = new GenericEntity<>(map, Map.class);\n        return Response.ok(genericEntity).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(\"Ljavax/ws/rs/core/GenericEntity<Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>;>;\");\n        result.getEntityTypes().add(\"Ljavax/ws/rs/core/GenericEntity;\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass19.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport javax.ws.rs.core.Variant;\nimport java.net.URI;\nimport java.util.*;\n\npublic class TestClass19 {\n\n    // test all available static Response methods\n    @javax.ws.rs.GET public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.accepted();\n        responseBuilder = Response.created(URI.create(\"\"));\n        responseBuilder = Response.noContent();\n        responseBuilder = Response.notAcceptable(new LinkedList<>());\n        responseBuilder = Response.notModified();\n        responseBuilder = Response.ok();\n        responseBuilder = Response.ok(1L, new Variant(MediaType.TEXT_PLAIN_TYPE, Locale.ENGLISH, \"UTF-8\"));\n        responseBuilder = Response.seeOther(URI.create(\"\"));\n        responseBuilder = Response.serverError();\n        responseBuilder = Response.temporaryRedirect(URI.create(\"\"));\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n        final HttpResponse thirdResult = new HttpResponse();\n        final HttpResponse fourthResult = new HttpResponse();\n        final HttpResponse fifthResult = new HttpResponse();\n        final HttpResponse sixthResult = new HttpResponse();\n        final HttpResponse seventhResult = new HttpResponse();\n        final HttpResponse eighthResult = new HttpResponse();\n        final HttpResponse ninthResult = new HttpResponse();\n        final HttpResponse tenthResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        secondResult.getStatuses().add(201);\n        thirdResult.getStatuses().add(204);\n        fourthResult.getStatuses().add(406);\n        fifthResult.getStatuses().add(304);\n        sixthResult.getStatuses().add(200);\n        seventhResult.getStatuses().add(200);\n        eighthResult.getStatuses().add(303);\n        ninthResult.getStatuses().add(500);\n        tenthResult.getStatuses().add(307);\n\n        seventhResult.getEntityTypes().add(Types.LONG);\n\n        secondResult.getHeaders().add(\"Location\");\n        fourthResult.getHeaders().add(\"Vary\");\n        eighthResult.getHeaders().add(\"Location\");\n        tenthResult.getHeaders().add(\"Location\");\n        seventhResult.getHeaders().addAll(Arrays.asList(\"Content-Language\", \"Content-Encoding\"));\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult, thirdResult, fourthResult, fifthResult, sixthResult,\n                seventhResult, eighthResult, ninthResult, tenthResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass2 {\n\n    @javax.ws.rs.GET public Response method() {\n        int status = 200;\n        if ((status = 300) > 0) {\n            status = 100;\n        }\n        return Response.status(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(Arrays.asList(100, 200, 300));\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass20.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.EntityTag;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass20 {\n\n    // continue testing all available static Response methods\n    @javax.ws.rs.GET public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.accepted(\"Hello\");\n        responseBuilder = Response.notModified(new EntityTag(\"\"));\n        responseBuilder = Response.ok(1, MediaType.APPLICATION_XML);\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n        final HttpResponse thirdResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        firstResult.getEntityTypes().add(Types.STRING);\n\n        secondResult.getStatuses().add(304);\n        secondResult.getHeaders().add(\"ETag\");\n\n        thirdResult.getStatuses().add(200);\n        thirdResult.getContentTypes().add(\"application/xml\");\n        thirdResult.getEntityTypes().add(Types.INTEGER);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult, thirdResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass21.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport javax.ws.rs.core.Variant;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Locale;\nimport java.util.Set;\n\npublic class TestClass21 {\n\n    // continue testing all available static Response methods\n    @javax.ws.rs.GET\n    public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.notModified(\"\");\n        responseBuilder = Response.ok(1d, MediaType.APPLICATION_JSON_TYPE);\n        responseBuilder = Response.ok(1L, new Variant(MediaType.TEXT_PLAIN_TYPE, Locale.ENGLISH, \"UTF-8\"));\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n        final HttpResponse thirdResult = new HttpResponse();\n\n        firstResult.getStatuses().add(304);\n        firstResult.getHeaders().add(\"ETag\");\n\n        secondResult.getStatuses().add(200);\n        secondResult.getContentTypes().add(\"application/json\");\n        secondResult.getEntityTypes().add(\"Ljava/lang/Double;\");\n\n        thirdResult.getStatuses().add(200);\n        thirdResult.getHeaders().addAll(Arrays.asList(\"Content-Language\", \"Content-Encoding\"));\n        thirdResult.getEntityTypes().add(Types.LONG);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult, thirdResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass22.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.CacheControl;\nimport javax.ws.rs.core.EntityTag;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.net.URI;\nimport java.util.*;\n\npublic class TestClass22 {\n\n    // test all available non-static Response methods\n    @javax.ws.rs.GET public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.ok();\n        responseBuilder.header(\"X-Test\", \"Hello\");\n        responseBuilder.cacheControl(CacheControl.valueOf(\"\"));\n        responseBuilder.contentLocation(URI.create(\"\"));\n        responseBuilder.cookie();\n        responseBuilder.entity(12d);\n        responseBuilder.expires(new Date());\n        responseBuilder.language(Locale.ENGLISH);\n        responseBuilder.encoding(\"UTF-8\");\n        responseBuilder.lastModified(new Date());\n        responseBuilder.link(URI.create(\"\"), \"rel\");\n        responseBuilder.location(URI.create(\"\"));\n        responseBuilder.status(433);\n        responseBuilder.tag(new EntityTag(\"\"));\n        responseBuilder.type(MediaType.APPLICATION_JSON_TYPE);\n        responseBuilder.variants(new LinkedList<>());\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(Arrays.asList(200, 433));\n        result.getEntityTypes().add(Types.DOUBLE);\n        result.getHeaders().addAll(Arrays.asList(\"X-Test\", \"Cache-Control\", \"Set-Cookie\", \"Expires\", \"Content-Language\", \"Content-Encoding\",\n                \"Last-Modified\", \"Link\", \"Location\", \"ETag\", \"Vary\", \"Content-Location\"));\n        result.getContentTypes().add(\"application/json\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass23.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.lang.annotation.Annotation;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static java.util.Collections.singletonList;\n\npublic class TestClass23 {\n\n    // continue testing all available non-static Response methods\n    @javax.ws.rs.GET\n    public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.ok();\n        responseBuilder.entity(12L, new Annotation[0]);\n        responseBuilder.link(\"\", \"rel\");\n        responseBuilder.status(Response.Status.EXPECTATION_FAILED);\n        responseBuilder.tag(\"\");\n        responseBuilder.type(MediaType.APPLICATION_XML);\n        responseBuilder.variants();\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(Arrays.asList(200, 417));\n        result.getEntityTypes().addAll(singletonList(Types.LONG));\n        result.getHeaders().addAll(Arrays.asList(\"Link\", \"ETag\", \"Vary\"));\n        result.getContentTypes().add(\"application/xml\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass24.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Link;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport javax.ws.rs.core.Variant;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Locale;\nimport java.util.Set;\n\npublic class TestClass24 {\n\n    // continue testing all available non-static Response methods\n    @javax.ws.rs.GET public Response method() {\n        Response.ResponseBuilder responseBuilder = Response.ok();\n        responseBuilder.links(new Link[0]);\n        responseBuilder.variant(new Variant(MediaType.TEXT_PLAIN_TYPE, Locale.ENGLISH, \"UTF-8\"));\n\n        return responseBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().addAll(Arrays.asList(200));\n        result.getHeaders().addAll(Arrays.asList(\"Link\", \"Content-Language\", \"Content-Encoding\"));\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass25.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.Supplier;\n\npublic class TestClass25 {\n\n    @javax.ws.rs.GET public Response method() {\n        final Supplier<Response> responseSupplier = () -> {\n            Response.ResponseBuilder builder = Response.ok();\n            builder.header(\"X-Test\", \"Hello World\");\n            return builder.build();\n        };\n        return responseSupplier.get();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Test\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass26.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.Supplier;\n\npublic class TestClass26 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final Supplier<Response> responseSupplier = this::response;\n        return responseSupplier.get();\n    }\n\n    private Response response() {\n        final Response.ResponseBuilder builder = Response.status(Response.Status.ACCEPTED);\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(202);\n        result.getHeaders().add(\"X-Test\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass27.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.function.Supplier;\n\npublic class TestClass27 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        Supplier<Response> responseSupplier = this::response;\n        if (\"\".equals(\"\"))\n            responseSupplier = this::otherResponse;\n        return responseSupplier.get();\n    }\n\n    private Response otherResponse() {\n        return Response.serverError().build();\n    }\n\n    private Response response() {\n        final Response.ResponseBuilder builder = Response.status(Response.Status.ACCEPTED);\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        firstResult.getHeaders().add(\"X-Test\");\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass28.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.Supplier;\n\npublic class TestClass28 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        Supplier<Response> responseSupplier = TestClass28::response;\n        return responseSupplier.get();\n    }\n\n    private static Response response() {\n        final Response.ResponseBuilder builder = Response.status(Response.Status.ACCEPTED);\n        builder.header(\"X-Test\", \"Hello World\");\n        return builder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(202);\n        result.getHeaders().add(\"X-Test\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass29.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.function.Function;\n\npublic class TestClass29 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        Function<Response.Status, Response> responseSupplier = s -> Response.status(s).build();\n        if (\"\".equals(\"\"))\n            return responseSupplier.apply(Response.Status.INTERNAL_SERVER_ERROR);\n        return responseSupplier.apply(Response.Status.ACCEPTED);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass3 {\n\n    @javax.ws.rs.GET public Response method() {\n        int status = 200;\n        if ((status = 300) > 0) {\n            Response.status(status).build();\n        }\n        status = 100;\n        return Response.status(200).entity(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getEntityTypes().add(Types.INTEGER);\n        result.getStatuses().add(200);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass30.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.function.Function;\n\npublic class TestClass30 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        Function<Response.Status, Response> responseSupplier = this::response;\n        if (\"\".equals(\"\"))\n            return responseSupplier.apply(Response.Status.INTERNAL_SERVER_ERROR);\n        return responseSupplier.apply(Response.Status.ACCEPTED);\n    }\n\n    private Response response(final Response.Status status) {\n        return Response.status(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass31.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.net.URI;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.function.Function;\n\npublic class TestClass31 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        Function<Response.Status, Response> responseSupplier;\n        responseSupplier = this::responseWithHeader;\n        if (\"\".equals(\"\"))\n            responseSupplier = this::response;\n        else if (\"foo\".equals(\"foo\"))\n            responseSupplier = this::anotherResponse;\n\n        return responseSupplier.apply(Response.Status.OK);\n    }\n\n    private Response response(final Response.Status status) {\n        return Response.status(status).location(URI.create(\"\")).build();\n    }\n\n    private Response responseWithHeader(final Response.Status status) {\n        return Response.status(status).header(\"X-Test\", \"Test\").build();\n    }\n\n    private Response anotherResponse(final Response.Status status) {\n        Function<Response.Status, Response> responseSupplier = s -> Response.status(status).tag(\"\").build();\n        return responseSupplier.apply(status);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult= new HttpResponse();\n        final HttpResponse thirdResult = new HttpResponse();\n\n        firstResult.getStatuses().add(200);\n        firstResult.getHeaders().add(\"Location\");\n        secondResult.getStatuses().add(200);\n        secondResult.getHeaders().add(\"X-Test\");\n        thirdResult.getStatuses().add(200);\n        thirdResult.getHeaders().add(\"ETag\");\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult, thirdResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass32.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.Function;\n\npublic class TestClass32 {\n\n    @javax.ws.rs.GET public Response method() {\n        Function<Response.Status, Function<String, Response>> function = sta -> str -> Response.status(sta).header(str, \"Hello\").build();\n        return function.apply(Response.Status.OK).apply(\"X-Header\");\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass33.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\n\npublic class TestClass33 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        BiFunction<Response.Status, String, Response> responseSupplier = this::response;\n\n        return responseSupplier.apply(Response.Status.OK, \"X-Header\");\n    }\n\n    private Response response(final Response.Status status, final String string) {\n        Function<String, Function<Response.Status, Response>> function = str -> sta -> Response.status(sta).header(str, \"Hello\").build();\n        return function.apply(string).apply(status);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass34.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\n\npublic class TestClass34 {\n\n    private String foobar = \"foobar\";\n\n    @javax.ws.rs.GET public Response method() {\n        BiFunction<Response.Status, Integer, BiFunction<String, Double, Response>> function = (sta, i) -> (str, d) -> Response.status(sta).header(str, foobar).build();\n        return function.apply(Response.Status.OK, 1).apply(\"X-Header\", 1d);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass35.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\n\npublic class TestClass35 {\n\n    @javax.ws.rs.GET public Response method() {\n        BiFunction<Response.Status, Integer, BiFunction<String, Double, Response>> function = (sta, i) -> (str, d) -> Response.status(sta).header(str, \"Test\").build();\n        return function.apply(Response.Status.OK, 1).apply(\"X-Header\", 1d);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass36.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\n\npublic class TestClass36 {\n\n    @javax.ws.rs.GET public Response method() {\n        BiFunction<Response.Status, Integer, BiFunction<String, Double, Response>> function = (sta, i) -> response(sta);\n        return function.apply(Response.Status.OK, 1).apply(\"X-Header\", 1d);\n    }\n\n    private BiFunction<String, Double, Response> response(final Response.Status status) {\n        return (str, d) -> Response.status(status).header(str, \"Test\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass37.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass37 {\n\n    @javax.ws.rs.GET\n    public Response method() {\n        if (\"\".equals(\"\"))\n            return Response.accepted(Json.createArrayBuilder().add(true).add(\"hello\").build()).build();\n        return Response.status(200).entity(Json.createObjectBuilder().add(\"key\", \"value\").add(\"duke\", 42).build()).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        firstResult.getEntityTypes().add(JSON_ARRAY);\n\n        secondResult.getStatuses().add(200);\n        secondResult.getEntityTypes().add(JSON_OBJECT);\n\n        final JsonObject jsonObject = new JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(STRING, \"value\"));\n        jsonObject.getStructure().put(\"duke\", new Element(INTEGER, 42));\n\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(PRIMITIVE_BOOLEAN, 1));\n        jsonArray.getElements().add(new Element(STRING, \"hello\"));\n\n        firstResult.getInlineEntities().add(jsonArray);\n        secondResult.getInlineEntities().add(jsonObject);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass38.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.json.JsonStructure;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass38 {\n\n    @javax.ws.rs.GET\n    public Response method() {\n        JsonStructure structure = Json.createArrayBuilder().add(\"duke\").add(42).build();\n        if (\"\".equals(\"\"))\n            structure = Json.createObjectBuilder().add(\"duke\", 42).add(\"key\", \"value\").build();\n        return Response.ok(structure).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(\"Ljavax/json/JsonStructure;\");\n        result.getEntityTypes().add(Types.JSON_OBJECT);\n        result.getEntityTypes().add(Types.JSON_ARRAY);\n\n        final JsonObject jsonObject = new JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(Types.STRING, \"value\"));\n        jsonObject.getStructure().put(\"duke\", new Element(Types.INTEGER, 42));\n\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(Types.STRING, \"duke\"));\n        jsonArray.getElements().add(new Element(Types.INTEGER, 42));\n\n        result.getInlineEntities().add(jsonObject);\n        result.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass39.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collector;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.JSON_ARRAY;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.STRING;\n\npublic class TestClass39 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        return Response.ok(buildJsonArray()).build();\n    }\n\n    public javax.json.JsonArray buildJsonArray() {\n        final Collector<String, JsonArrayBuilder, JsonArrayBuilder> collector = Collector.of(Json::createArrayBuilder, JsonArrayBuilder::add,\n                JsonArrayBuilder::add);\n        return tasks.stream().map(Object::toString).\n                collect(collector).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(JSON_ARRAY);\n\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(STRING));\n\n        // TODO un-comment\n//        result.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass4 {\n\n    @javax.ws.rs.GET\n    public Response method() {\n        Response.Status status = Response.Status.OK;\n\n        if (\"\".equals(this.getClass().getName())) {\n            status = Response.Status.ACCEPTED;\n        }\n\n        return responseBuilder(status).entity(\"Test\").build();\n    }\n\n    private Response.ResponseBuilder responseBuilder(final Response.Status status) {\n        return Response.status(status).header(\"X-Test\", \"Test\");\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getEntityTypes().add(Types.STRING);\n        result.getStatuses().addAll(Arrays.asList(200, 202));\n        result.getHeaders().add(\"X-Test\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass40.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.json.JsonObjectBuilder;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\nimport java.util.function.BinaryOperator;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass40 {\n\n    @javax.ws.rs.GET\n    public Response method() {\n        BiFunction<JsonObjectBuilder, String, JsonObjectBuilder> function = JsonObjectBuilder::addNull;\n        BinaryOperator<JsonArrayBuilder> anotherFunction = JsonArrayBuilder::add;\n\n        JsonObjectBuilder builder = Json.createObjectBuilder();\n        function.apply(builder, \"test\");\n\n        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();\n        JsonArrayBuilder anotherArrayBuilder = Json.createArrayBuilder();\n\n        arrayBuilder.add(\"test1\");\n        anotherArrayBuilder.add(\"test2\");\n        anotherFunction.apply(arrayBuilder, anotherArrayBuilder);\n\n        builder.add(\"array\", arrayBuilder);\n\n        return Response.ok(builder.build()).build();\n    }\n\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(JSON_OBJECT);\n\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(STRING, \"test1\"));\n\n        final JsonArray nestedArray = new JsonArray();\n        nestedArray.getElements().add(new Element(STRING, \"test2\"));\n        jsonArray.getElements().add(new Element(JSON_ARRAY, nestedArray));\n\n        JsonObject jsonObject = new JsonObject();\n        jsonObject.getStructure().put(\"test\", new Element(OBJECT, null));\n        jsonObject.getStructure().put(\"array\", new Element(JSON_ARRAY, jsonArray));\n\n        result.getInlineEntities().add(jsonObject);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass41.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.function.BiFunction;\n\npublic class TestClass41 {\n\n    @javax.ws.rs.GET public Response method() {\n        final Response.Status status = Response.Status.OK;\n        BiFunction<Response.Status, Integer, BiFunction<String, Double, Response>> function = (sta, i) -> (str, d) -> Response.status(status).header(str, \"Test\").build();\n        return function.apply(Response.Status.NOT_FOUND, 1).apply(\"X-Header\", 1d);\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getHeaders().add(\"X-Header\");\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass42.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.*;\n\npublic class TestClass42 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        return Response.ok(buildJsonArray()).build();\n    }\n\n    public javax.json.JsonArray buildJsonArray() {\n        return tasks.stream().map(this::toObject).\n                collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add).build();\n    }\n\n    private javax.json.JsonObject toObject(final Object o) {\n        return Json.createObjectBuilder().add(\"key\", o.toString()).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(JSON_ARRAY);\n\n        final JsonArray jsonArray = new JsonArray();\n        final JsonObject jsonObject = new JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(STRING));\n        jsonArray.getElements().add(new Element(JSON_OBJECT, jsonObject));\n\n        result.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass43.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonArray;\n\nimport javax.json.Json;\nimport javax.json.JsonArrayBuilder;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.JSON_ARRAY;\nimport static com.sebastian_daschner.jaxrs_analyzer.model.Types.STRING;\n\npublic class TestClass43 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        return Response.ok(buildJsonArray()).build();\n    }\n\n    public javax.json.JsonArray buildJsonArray() {\n        final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();\n        tasks.stream().map(Object::toString).forEach(arrayBuilder::add);\n        return arrayBuilder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(JSON_ARRAY);\n\n        final JsonArray jsonArray = new JsonArray();\n        jsonArray.getElements().add(new Element(STRING));\n\n        result.getInlineEntities().add(jsonArray);\n\n        return Collections.singleton(result);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass44.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass44 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<User> users = new LinkedList<>();\n        return Response.ok(users).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        result.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass44$User;>;\");\n        result.getEntityTypes().add(\"Ljava/util/LinkedList;\");\n\n        return Collections.singleton(result);\n    }\n\n    private static class User {\n        private String name;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass45.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass45 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<User> users = new LinkedList<>();\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException();\n        return Response.ok(users).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n\n        firstResult.getStatuses().add(200);\n        firstResult.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass45$User;>;\");\n        firstResult.getEntityTypes().add(\"Ljava/util/LinkedList;\");\n\n        final HttpResponse secondResult = new HttpResponse();\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n    private static class User {\n        private String name;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass46.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class TestClass46 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<User> users = new LinkedList<>();\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(\"message\");\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(Response.accepted().build());\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", Response.status(Response.Status.GATEWAY_TIMEOUT).build());\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(201);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", 204);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(Response.Status.CONFLICT);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", Response.Status.FORBIDDEN);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(new RuntimeException(), Response.status(Response.Status.BAD_REQUEST).build());\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", new RuntimeException(), Response.status(Response.Status.NOT_IMPLEMENTED).build());\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(new RuntimeException(), 205);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", new RuntimeException(), 206);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(new RuntimeException(), Response.Status.EXPECTATION_FAILED);\n        else if (\"a\".equals(\"a\"))\n            throw new WebApplicationException(\"message\", new RuntimeException(), Response.Status.FOUND);\n        return Response.ok(users).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final Set<HttpResponse> results = new HashSet<>();\n\n        final HttpResponse firstResult = new HttpResponse();\n        firstResult.getStatuses().add(200);\n        firstResult.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass46$User;>;\");\n        firstResult.getEntityTypes().add(\"Ljava/util/LinkedList;\");\n        results.add(firstResult);\n\n        final int[] statuses = {500, 202, 504, 201, 204, 409, 403, 400, 501, 205, 206, 417, 302};\n        for (final int status : statuses) {\n            final HttpResponse response = new HttpResponse();\n            response.getStatuses().add(status);\n            results.add(response);\n        }\n\n        return results;\n    }\n\n    private static class User {\n        private String name;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass47.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass47 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<User> users = new LinkedList<>();\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(new RuntimeException());\n        return Response.ok(users).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n\n        firstResult.getStatuses().add(200);\n        firstResult.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass47$User;>;\");\n        firstResult.getEntityTypes().add(\"Ljava/util/LinkedList;\");\n\n        final HttpResponse secondResult = new HttpResponse();\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n    private static class User {\n        private String name;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass48.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass48 {\n\n    private List<Object> tasks;\n\n    @javax.ws.rs.GET\n    public Response method() {\n        List<User> users = new LinkedList<>();\n        if (\"\".equals(\"\"))\n            throw new WebApplicationException(\"message\", new RuntimeException());\n        return Response.ok(users).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n\n        firstResult.getStatuses().add(200);\n        firstResult.getEntityTypes().add(\"Ljava/util/List<Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass48$User;>;\");\n        firstResult.getEntityTypes().add(\"Ljava/util/LinkedList;\");\n\n        final HttpResponse secondResult = new HttpResponse();\n        secondResult.getStatuses().add(500);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n    private static class User {\n        private String name;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass49.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.PathParam;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass49 {\n\n    private Converter converter;\n\n    @javax.ws.rs.GET public Response method(@PathParam(\"input\") String input) {\n        return Response.status(Response.Status.OK).header(\"X-Info\", \"Converted: \" + converter.convert(input)).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(200);\n        response.getHeaders().add(\"X-Info\");\n\n        return Collections.singleton(response);\n    }\n\n    private interface Converter {\n        String convert(String string);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.persistence.EntityManager;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass5 {\n\n    private EntityManager entityManager;\n\n    @javax.ws.rs.GET public Response method() {\n\n        final TestClass5 testClass = entityManager.find(TestClass5.class, 1);\n\n        if (testClass.method().hasEntity())\n            return buildWithStatus(Response.Status.ACCEPTED);\n\n        return buildWithStatus(Response.Status.CONFLICT);\n    }\n\n    private static Response buildWithStatus(final Response.Status status) {\n        return Response.status(status).header(\"X-Message\", \"Secret message\").build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(202);\n        firstResult.getHeaders().add(\"X-Message\");\n\n\n        secondResult.getStatuses().add(409);\n        secondResult.getHeaders().add(\"X-Message\");\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass50.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.PathParam;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass50 {\n\n    private Converter converter;\n\n    @javax.ws.rs.GET public Response method(@PathParam(\"input\") String input) {\n        return Response.status(Response.Status.OK).header(\"X-Info\", \"Converted: \" + converter.convert(input)).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(200);\n        response.getHeaders().add(\"X-Info\");\n\n        return Collections.singleton(response);\n    }\n\n    private interface Converter {\n        String convert(String string);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass51.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.PathParam;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass51 {\n\n    private static final int STATUS = 404;\n\n    @javax.ws.rs.GET public Response method(@PathParam(\"input\") String input) {\n        return Response.status(STATUS).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(404);\n\n        return Collections.singleton(response);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass52.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.PathParam;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass52 {\n\n    public static final TestClass52 TEST = new TestClass52();\n\n    @javax.ws.rs.GET public Response method(@PathParam(\"input\") String input) {\n        return Response.status(TEST.getStatus()).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(200);\n\n        return Collections.singleton(response);\n    }\n\n    public int getStatus() {\n        return 200;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass53.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass53 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final InnerTestClass innerTestClass = new InnerTestClass(400);\n        final int status = innerTestClass.method();\n        return Response.status(status).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(404);\n\n        return Collections.singleton(result);\n    }\n\n    private class InnerTestClass {\n\n        public InnerTestClass(final int number) {\n            System.out.println(number);\n        }\n\n        @javax.ws.rs.GET public int method() {\n            return 404;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass54.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass54 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        final Response.ResponseBuilder builder = Response.status(200);\n        final InnerTestClass innerTestClass = new InnerTestClass(builder);\n        System.out.println(innerTestClass);\n        return builder.build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(200);\n        // TODO un-comment, relevant instruction reducer reduces all instructions of InnerTestClass due to missing return\n        // -> needs to take care of parameter as well\n//        result.getHeaders().add(\"X-Info\");\n\n        return Collections.singleton(result);\n    }\n\n    private class InnerTestClass {\n\n        public InnerTestClass(final Response.ResponseBuilder builder) {\n            builder.header(\"X-Info\", \"Test\");\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass55.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass55 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        if (\"\".equals(\"\"))\n            return Response.status(status(Integer.valueOf(1))).build();\n        return Response.status(status(1)).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResponse = new HttpResponse();\n        firstResponse.getStatuses().add(200);\n\n        final HttpResponse secondResponse = new HttpResponse();\n        secondResponse.getStatuses().add(201);\n\n        return new HashSet<>(Arrays.asList(firstResponse, secondResponse));\n    }\n\n    private int status(final int number) {\n        return 200;\n    }\n\n    private int status(final Integer number) {\n        return 201;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass56.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass56 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        return createResponse(TestEnum.FIRST);\n    }\n\n    private Response createResponse(final TestEnum test) {\n        return Response.status(test.getStatus()).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        // TODO un-comment\n//        final HttpResponse firstResponse = new HttpResponse();\n//        firstResponse.getStatuses().add(200);\n\n//        final HttpResponse secondResponse = new HttpResponse();\n//        secondResponse.getStatuses().add(201);\n\n//        return new HashSet<>(Arrays.asList(firstResponse, secondResponse));\n        return Collections.singleton(new HttpResponse());\n    }\n\n}\n\nenum TestEnum {\n    FIRST(200),\n    SECOND(201);\n\n    private final int status;\n\n    TestEnum(final int status) {\n        this.status = status;\n    }\n\n    public int getStatus() {\n        return status;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass57.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass57 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        return Response.status(save(id)).build();\n    }\n\n    private int save(final String id) {\n        if (\"\".equals(id))\n            return save(id);\n        return 200;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(200);\n\n        return Collections.singleton(response);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass58.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass58 {\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        return Response.status(save(id)).build();\n    }\n\n    private int save(final String id) {\n        return saveInternal(id);\n    }\n\n    private int saveInternal(final String id) {\n        if (\"\".equals(\"\"))\n            return saveInternal2(id + 1);\n        return 200;\n    }\n\n    private int saveInternal2(final String s) {\n        if (\"\".equals(\"\"))\n            return saveInternal(s + 2);\n        return 201;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse response = new HttpResponse();\n        response.getStatuses().add(200);\n        response.getStatuses().add(201);\n\n        return Collections.singleton(response);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass59.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass59 {\n\n    ConfigurationManager configurationManager;\n\n    @javax.ws.rs.GET\n    public Response method(final String name) {\n        ConfigurationManager.Configuration configuration = this.configurationManager.getConfiguration(name);\n        if (configuration == null)\n            return Response.noContent().build();\n        return Response.ok(configuration).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse responseFound = new HttpResponse();\n        responseFound.getStatuses().add(200);\n        responseFound.getEntityTypes().add(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass59$ConfigurationManager$Configuration;\");\n\n        final HttpResponse responseNotFound = new HttpResponse();\n        responseNotFound.getStatuses().add(204);\n\n        return new HashSet<>(Arrays.asList(responseFound, responseNotFound));\n    }\n\n    private interface ConfigurationManager {\n        Configuration getConfiguration(String name);\n\n        class Configuration {\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.persistence.EntityManager;\nimport javax.persistence.EntityNotFoundException;\nimport javax.ws.rs.core.Response;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClass6 {\n\n    private InnerTestClass6 innerTestClass;\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        try {\n            innerTestClass.method(id);\n            return Response.noContent().build();\n        } catch (EntityNotFoundException e) {\n            return Response.status(Response.Status.NOT_FOUND).header(\"X-Message\", \"The entity with identifier \" + id + \" was not found.\").build();\n        }\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse firstResult = new HttpResponse();\n        final HttpResponse secondResult = new HttpResponse();\n\n        firstResult.getStatuses().add(404);\n        firstResult.getHeaders().add(\"X-Message\");\n\n        secondResult.getStatuses().add(204);\n\n        return new HashSet<>(Arrays.asList(firstResult, secondResult));\n    }\n\n    private class InnerTestClass6 {\n\n        private EntityManager entityManager;\n\n        @javax.ws.rs.GET public void method(final String id) {\n            final Object managedEntity = entityManager.find(Object.class, id);\n            entityManager.remove(managedEntity);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass60.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.*;\n\npublic class TestClass60 {\n\n    ConfigurationManager configurationManager;\n\n    @javax.ws.rs.GET\n    public Response method(final String name) {\n        ConfigurationManager.Configuration configuration = this.configurationManager.getConfiguration(name);\n        if (configuration == null)\n            return Response.noContent().build();\n        return Response.ok(configuration).build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse responseFound = new HttpResponse();\n        responseFound.getStatuses().add(200);\n        responseFound.getEntityTypes().add(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass60$ConfigurationManager$Configuration;\");\n        responseFound.getEntityTypes().add(Types.OBJECT);\n\n        final HttpResponse responseNotFound = new HttpResponse();\n        responseNotFound.getStatuses().add(204);\n\n        return new HashSet<>(Arrays.asList(responseFound, responseNotFound));\n    }\n\n    private class ConfigurationManager {\n        public Configuration getConfiguration(String cacheName) {\n            Map<String, String> cache = new HashMap<>();\n            if (cache == null) {\n                return null;\n            }\n            Configuration configuration = (Configuration) new Object();\n            if (configuration == null) {\n                return null;\n            }\n            boolean active = configuration.isActive();\n            return new Configuration(active);\n        }\n\n        class Configuration {\n            public Configuration() {\n            }\n\n            public Configuration(final boolean active) {\n            }\n\n            boolean isActive() {\n                return new Random().nextBoolean();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass61.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass61 {\n\n    @javax.ws.rs.GET public Response method(final String name) {\n        return Response.ok(getInstance(String.class)).build();\n    }\n\n    public <T> T getInstance(final Class<T> clazz) {\n        // some reflection magic\n        return null;\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse responseFound = new HttpResponse();\n        responseFound.getStatuses().add(200);\n        // TODO uncomment analyze generic method type inference\n//        responseFound.getEntityTypes().add(Types.STRING);\n        responseFound.getEntityTypes().add(Types.OBJECT);\n\n        return Collections.singleton(responseFound);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass62.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\n\n// https://github.com/sdaschner/jaxrs-analyzer/issues/80\npublic class TestClass62 {\n\n    @GET\n    public Response method() {\n        // scope will cause variable indexes 1 for i and contentType\n        for (int i = 0; i < 0; i++) ;\n\n        final String contentType = null;\n\n        return Response\n                .ok()\n                .type(contentType)\n                .build();\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse responseFound = new HttpResponse();\n        responseFound.getStatuses().add(200);\n\n        return Collections.singleton(responseFound);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.persistence.EntityManager;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.logging.Logger;\n\npublic class TestClass7 {\n\n    private InnerTestClass6 innerTestClass;\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        try {\n            innerTestClass.method(id);\n            return Response.noContent().build();\n        } finally {\n            Logger.getLogger(\"\").info(\"deleted\");\n        }\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(204);\n\n        return Collections.singleton(result);\n    }\n\n    private class InnerTestClass6 {\n\n        private EntityManager entityManager;\n\n        public void method(final String id) {\n            final Object managedEntity = entityManager.find(Object.class, id);\n            entityManager.remove(managedEntity);\n            if (\"\".equals(id))\n                throw new RuntimeException(\"\");\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.persistence.EntityManager;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.logging.Logger;\n\npublic class TestClass8 {\n\n    private InnerTestClass6 innerTestClass;\n\n    @javax.ws.rs.GET\n    public Response method(final String id) {\n        try {\n            final int status = innerTestClass.method(id.length());\n            String string = innerTestClass.getModel(null);\n            return Response.status(status).header(\"X-Foo\", string).build();\n        } finally {\n            Logger.getLogger(\"\").info(\"deleted\");\n        }\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(404);\n        result.getHeaders().add(\"X-Foo\");\n\n        return Collections.singleton(result);\n    }\n\n    private class InnerTestClass6 {\n\n        private EntityManager entityManager;\n\n        public String getModel(final String id) {\n            return new String(id);\n        }\n\n        public int method(final int number) {\n            synchronized (this) {\n                System.out.println(3 * 2 / number);\n                return 404;\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/classes/testclasses/resource/response/TestClass9.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.classes.testclasses.resource.response;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\n\nimport javax.persistence.EntityManager;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.logging.Logger;\n\npublic class TestClass9 {\n\n    private InnerTestClass6 innerTestClass;\n\n    @javax.ws.rs.GET public Response method(final String id) {\n        try {\n            synchronized (this) {\n                final int status = innerTestClass.method(id.length());\n                return Response.status(status).build();\n            }\n        } finally {\n            Logger.getLogger(\"\").info(\"deleted\");\n        }\n    }\n\n    public static Set<HttpResponse> getResult() {\n        final HttpResponse result = new HttpResponse();\n\n        result.getStatuses().add(404);\n\n        return Collections.singleton(result);\n    }\n\n    private class InnerTestClass6 {\n\n        private EntityManager entityManager;\n\n        @javax.ws.rs.GET public int method(final int number) {\n            synchronized (this) {\n                System.out.println(3 * 2 / number);\n                return 404;\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/javadoc/ResponseCommentExtractorTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.javadoc;\n\nimport com.sebastian_daschner.jaxrs_analyzer.utils.Pair;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Collection;\n\nimport static java.util.Arrays.asList;\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(Parameterized.class)\npublic class ResponseCommentExtractorTest {\n\n    @Parameterized.Parameter\n    public String commentText;\n\n    @Parameterized.Parameter(1)\n    public Pair<Integer, String> expected;\n\n    @Test\n    public void testExtract() {\n        assertThat(ResponseCommentExtractor.extract(commentText), is(expected));\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        return asList(\n                data(\"300 hello world\", 300, \"hello world\"),\n                data(\"200 hello world\", 200, \"hello world\"),\n                data(\"200  hello world \", 200, \"hello world\"),\n                data(\" 200  hello world \", 200, \"hello world\"),\n                data(\"\\t200\\thello\\tworld \", 200, \"hello\\tworld\"),\n                nullData(\"hello world\")\n        );\n    }\n\n    private static Object[] data(String commentText, int status, String comment) {\n        return new Object[]{commentText, Pair.of(status, comment)};\n    }\n\n    private static Object[] nullData(String commentText) {\n        return new Object[]{commentText, null};\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/ClassAnalyzerTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes;\n\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.BytecodeAnalyzer;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.classes.JAXRSClassVisitor;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.Set;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(Parameterized.class)\npublic class ClassAnalyzerTest {\n\n    private final String testClassSimpleName;\n    private final String testClass;\n    private final ClassResult expectedResult;\n\n    public ClassAnalyzerTest(final String testClassSimpleName, final String testClass, final ClassResult expectedResult) throws NotFoundException {\n        this.testClassSimpleName = testClassSimpleName;\n        this.testClass = testClass;\n        this.expectedResult = expectedResult;\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() throws NotFoundException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = TestClassUtils.getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses\");\n\n        for (final String testClass : testClasses) {\n            if (!testClass.contains(\"/TestClass\"))\n                continue;\n\n            final Object[] testData = new Object[3];\n\n            testData[0] = testClass.substring(testClass.lastIndexOf('/') + 1);\n            testData[1] = testClass;\n\n            // evaluate static \"getResult\"-method\n            testData[2] = JavaUtils.loadClassFromName(testClass).getDeclaredMethod(\"getResult\").invoke(null);\n\n            data.add(testData);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() throws IOException {\n        final ClassReader classReader = new ContextClassReader(testClass);\n        final ClassResult actualResult = new ClassResult();\n        final ClassVisitor visitor = new JAXRSClassVisitor(actualResult);\n        classReader.accept(visitor, ClassReader.EXPAND_FRAMES);\n        new BytecodeAnalyzer().analyzeBytecode(actualResult);\n\n        assertEquals(testClass, expectedResult, actualResult);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\n\n@Path(\"test\")\npublic class TestClass1 {\n\n    @GET\n    public int method() {\n        int status = 200;\n        int anotherStatus = 100;\n        status = anotherStatus = 300;\n        return status;\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult methodResult = MethodResultBuilder.withResponses(HttpResponseBuilder.newBuilder().andEntityTypes(Types.PRIMITIVE_INT).build())\n                .andMethod(HttpMethod.GET).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(methodResult).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass10.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Path(\"test\")\npublic class TestClass10 extends ATestClass10 {\n\n    @Override\n    public Response getInfo(final String info) {\n        final Map<String, Integer> map = new HashMap<>();\n        map.put(info, 100);\n        return createResponse(map);\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).andHeaders(\"X-Test\").build())\n                .andPath(\"{info}\").andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n\nabstract class ATestClass10 {\n\n    @POST\n    @Path(\"{info}\")\n    public abstract Response getInfo(final String info);\n\n    protected final Response createResponse(final Map<String, Integer> map) {\n        return Response.ok(\"hello\").header(\"X-Test\", \"world\").build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass11.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.GenericEntity;\nimport javax.ws.rs.core.Response;\nimport java.util.Collections;\nimport java.util.List;\n\n@Path(\"test\")\npublic class TestClass11 extends ATestClass11 {\n\n    @Override\n    public Response getInfo(final String info) {\n        return Response.ok(getContent(info)).build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(\"Ljavax/ws/rs/core/GenericEntity;\",\n                \"Ljavax/ws/rs/core/GenericEntity<Ljava/util/List<Ljava/lang/String;>;>;\").build())\n                .andPath(\"{info}\").andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n\nabstract class ATestClass11 {\n\n    @POST\n    @Path(\"{info}\")\n    public abstract Response getInfo(final String info);\n\n    protected final GenericEntity<List<String>> getContent(final String content) {\n        // TODO change to direct return, without variable declaration\n        final GenericEntity<List<String>> entity = new GenericEntity<>(Collections.singletonList(content), List.class);\n        return entity;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass12.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\npublic class TestClass12<T> {\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(final T info) {\n        return Response.ok().header(\"X-Info\", info + \" is complex\").build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andHeaders(\"X-Info\").build()).andPath(\"{info}\")\n                .andMethod(HttpMethod.GET).andRequestBodyType(Types.OBJECT).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass13.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\npublic class TestClass13<T extends TestClass13.Model> {\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(final T info) {\n        return Response.ok().header(\"X-Info\", info + \" is complex\").build();\n    }\n\n    public static ClassResult getResult() {\n        // TODO uncomment to resolve type variable bounds\n//        final Type type = new Type(\"com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses.TestClass13$Model\");\n        final String type = Types.OBJECT;\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andHeaders(\"X-Info\").build()).andPath(\"{info}\")\n                .andMethod(HttpMethod.GET).andRequestBodyType(type).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n    public interface Model {\n        String getString();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass14.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.DefaultValue;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.Response;\n\n// not meant to be correct JAX-RS code, just for test purposes\n// #55 - support for @DefaultValue annotation\n@Path(\"test\")\npublic class TestClass14 {\n\n    @DefaultValue(\"1\")\n    @QueryParam(\"id\")\n    private Integer id;\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(@DefaultValue(\"1\") @QueryParam(\"value\") final Integer value) {\n        return Response.ok().build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).build())\n                .andPath(\"{info}\")\n                .andMethod(HttpMethod.GET)\n                .andQueryParam(\"value\", Types.INTEGER, \"1\")\n                .build();\n\n        return ClassResultBuilder\n                .withResourcePath(\"test\")\n                .andMethods(method)\n                .andQueryParam(\"id\", Types.INTEGER, \"1\")\n                .build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass15.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.DefaultValue;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.Response;\n\n// not meant to be correct JAX-RS code, just for test purposes\n// #50 enum JAX-RS parameter representations\n@Path(\"test\")\npublic class TestClass15 {\n\n    @DefaultValue(\"FIRST\")\n    @QueryParam(\"id\")\n    private InnerTestClass15 id;\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(@DefaultValue(\"FIRST\") @QueryParam(\"value\") final InnerTestClass15 value) {\n        return Response.ok().build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).build())\n                .andPath(\"{info}\")\n                .andMethod(HttpMethod.GET)\n                .andQueryParam(\"value\", \"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass15$InnerTestClass15;\", \"FIRST\")\n                .build();\n\n        return ClassResultBuilder\n                .withResourcePath(\"test\")\n                .andMethods(method)\n                .andQueryParam(\"id\", \"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass15$InnerTestClass15;\", \"FIRST\")\n                .build();\n    }\n\n    private enum InnerTestClass15 {\n        FIRST, SECOND, THIRD\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass16.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.DefaultValue;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.Response;\n\n// not meant to be correct JAX-RS code, just for test purposes\n// #59 JSR 339 String auto-convertible types\n@Path(\"test\")\npublic class TestClass16 {\n\n    @DefaultValue(\"1\")\n    @QueryParam(\"id\")\n    private StringValueOfParam id;\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(@DefaultValue(\"1\") @QueryParam(\"value\") final StringFromStringParam value) {\n        return Response.ok().build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).build())\n                .andPath(\"{info}\")\n                .andMethod(HttpMethod.GET)\n                .andQueryParam(\"value\", \"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass16$StringFromStringParam;\", \"1\")\n                .build();\n\n        return ClassResultBuilder\n                .withResourcePath(\"test\")\n                .andMethods(method)\n                .andQueryParam(\"id\", \"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass16$StringValueOfParam;\", \"1\")\n                .build();\n    }\n\n    private static class StringValueOfParam {\n        public static StringValueOfParam valueOf(String value) {\n            return null;\n        }\n    }\n\n    private static class StringFromStringParam {\n        public static StringFromStringParam fromString(String value) {\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\n@Produces(MediaType.APPLICATION_JSON)\npublic class TestClass2 {\n\n    @GET\n    @Produces(MediaType.TEXT_HTML)\n    public int method() {\n        int status = 200;\n        return status;\n    }\n\n    @POST\n    public Response post(final String string) {\n        return Response.accepted().build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult firstMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.newBuilder().andEntityTypes(Types.PRIMITIVE_INT)\n                .andContentTypes(\"text/html\").build())\n                .andResponseMediaTypes(\"text/html\").andMethod(HttpMethod.GET).build();\n        final MethodResult secondMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(202).build())\n                .andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andResponseMediaTypes(\"application/json\").andMethods(firstMethod, secondMethod).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.core.MediaType;\n\n@Path(\"test\")\n@Produces(MediaType.APPLICATION_JSON)\npublic class TestClass3 {\n\n    @GET\n    public JsonObject method() {\n        return Json.createObjectBuilder().add(\"key\", \"value\").add(\"duke\", 42).build();\n    }\n\n    public static ClassResult getResult() {\n        final com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject jsonObject = new com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonObject();\n        jsonObject.getStructure().put(\"key\", new Element(Types.STRING, \"value\"));\n        jsonObject.getStructure().put(\"duke\", new Element(Types.INTEGER, 42));\n        final MethodResult firstMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.newBuilder().andEntityTypes(Types.JSON_OBJECT)\n                .andInlineEntities(jsonObject).build())\n                .andMethod(HttpMethod.GET).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andResponseMediaTypes(\"application/json\").andMethods(firstMethod).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\npublic class TestClass4 {\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(final String info) {\n        return Response.ok().header(\"X-Info\", info + \" is complex\").build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andHeaders(\"X-Info\").build()).andPath(\"{info}\")\n                .andMethod(HttpMethod.GET).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\npublic abstract class TestClass5 {\n\n    @GET\n    @Path(\"{info}\")\n    public abstract Response getInfo(final String info);\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.newBuilder().andPath(\"{info}\").andMethod(HttpMethod.GET).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\n\n@Path(\"test\")\npublic interface TestClass6 {\n\n    @GET\n    @Path(\"{info}\")\n    Model getInfo(final String info);\n\n    static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.newBuilder()\n                .andEntityTypes(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass6$Model;\").build())\n                .andPath(\"{info}\").andMethod(HttpMethod.GET).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n    class Model {\n\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\n\n@Path(\"test\")\npublic abstract class TestClass7 {\n\n    @POST\n    @Path(\"{info}\")\n    public abstract void getInfo(final String info);\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.newBuilder().andPath(\"{info}\").andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\n\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.core.Response;\n\n@Path(\"test\")\npublic class TestClass8 extends ATestClass8 {\n\n    @Override\n    public Response getInfo(final String info) {\n        return createResponse();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).andHeaders(\"X-Test\").build())\n                .andPath(\"{info}\").andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n    }\n\n}\n\nabstract class ATestClass8 {\n\n    @POST\n    @Path(\"{info}\")\n    public abstract Response getInfo(final String info);\n\n    protected final Response createResponse() {\n        return Response.ok(\"hello\").header(\"X-Test\", \"world\").build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/project/classes/testclasses/TestClass9.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.project.classes.testclasses;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.Response;\nimport java.util.Map;\n\n// not meant to be correct JAX-RS code, just for test purposes\n@Path(\"test\")\npublic class TestClass9 {\n\n    @QueryParam(\"definitions\")\n    private Map<String, Integer> definitions;\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(final Map<String, String> info) {\n        return Response.ok().build();\n    }\n\n    public static ClassResult getResult() {\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).build())\n                .andPath(\"{info}\").andMethod(HttpMethod.GET).andRequestBodyType(\"Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>;\")\n                .build();\n        return ClassResultBuilder.withResourcePath(\"test\").andMethods(method).andQueryParam(\"definitions\", \"Ljava/util/Map<Ljava/lang/String;Ljava/lang/Integer;>;\").build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/DynamicTypeAnalyzerTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.json.Json;\nimport javax.json.JsonNumber;\nimport javax.json.JsonString;\nimport javax.json.JsonValue;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.STRING_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.STRING_LIST_IDENTIFIER;\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\npublic class DynamicTypeAnalyzerTest {\n\n    private DynamicTypeAnalyzer cut;\n    private Map<TypeIdentifier, TypeRepresentation> typeRepresentations;\n\n    @Before\n    public void setUp() {\n        typeRepresentations = new HashMap<>();\n        cut = new DynamicTypeAnalyzer(typeRepresentations);\n    }\n\n    @Test\n    public void testPrimitives() {\n        TypeIdentifier identifier = cut.analyze(JsonValue.FALSE);\n        assertThat(identifier.getType(), is(Types.PRIMITIVE_BOOLEAN));\n\n        identifier = cut.analyze(JsonValue.TRUE);\n        assertThat(identifier.getType(), is(Types.PRIMITIVE_BOOLEAN));\n\n        identifier = cut.analyze(JsonValue.NULL);\n        assertThat(identifier.getType(), is(Types.OBJECT));\n\n        identifier = cut.analyze(jsonString(\"\"));\n        assertThat(identifier.getType(), is(Types.STRING));\n\n        identifier = cut.analyze(jsonNumber(0.5));\n        assertThat(identifier.getType(), is(Types.DOUBLE));\n\n        assertThat(typeRepresentations.size(), is(0));\n    }\n\n    @Test\n    public void testArraysAndObjects() {\n        TypeIdentifier identifier = cut.analyze(Json.createArrayBuilder().add(\"string\").build());\n        final String firstName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        identifier = cut.analyze(Json.createObjectBuilder().add(\"key\", 0).build());\n        final String secondName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        assertThat(typeRepresentations.size(), is(2));\n\n        final TypeRepresentation.CollectionTypeRepresentation collection = getRepresentation(firstName);\n        assertThat(collection.getIdentifier().getName(), is(firstName));\n        assertThat(collection.getComponentType().getType(), is(Types.STRING));\n\n        final TypeRepresentation.ConcreteTypeRepresentation concrete = getRepresentation(secondName);\n        assertThat(concrete.getIdentifier().getName(), is(secondName));\n        assertThat(concrete.getProperties().size(), is(1));\n        assertThat(concrete.getProperties().get(\"key\").getType(), is(Types.DOUBLE));\n    }\n\n    @Test\n    public void testArraysAndObjectsNestedTypes() {\n        TypeIdentifier identifier = cut.analyze(Json.createArrayBuilder().add(Json.createObjectBuilder().add(\"key\", \"value\").add(\"number\", 10.0)).build());\n        final String firstName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        identifier = cut.analyze(Json.createObjectBuilder().add(\"key\", 0).add(\"object\", Json.createObjectBuilder().add(\"string\", \"value\"))\n                .add(\"array\", Json.createArrayBuilder().add(\"string\")).build());\n        final String secondName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        assertThat(typeRepresentations.size(), is(5));\n\n        TypeRepresentation.CollectionTypeRepresentation collection = getRepresentation(firstName);\n        final String thirdName = collection.getComponentType().getName();\n        assertThat(collection.getIdentifier().getName(), is(firstName));\n        assertThat(collection.getComponentType().getType(), is(Types.JSON));\n\n        TypeRepresentation.ConcreteTypeRepresentation concrete = getRepresentation(thirdName);\n        assertThat(concrete.getIdentifier().getName(), is(thirdName));\n        assertThat(concrete.getProperties().size(), is(2));\n        assertThat(concrete.getProperties().get(\"key\").getType(), is(Types.STRING));\n        assertThat(concrete.getProperties().get(\"number\").getType(), is(Types.DOUBLE));\n\n        concrete = getRepresentation(secondName);\n        assertThat(concrete.getIdentifier().getName(), is(secondName));\n        assertThat(concrete.getProperties().size(), is(3));\n        assertThat(concrete.getProperties().get(\"key\").getType(), is(Types.DOUBLE));\n        final String fourthName = concrete.getProperties().get(\"object\").getName();\n        assertThat(concrete.getProperties().get(\"object\").getType(), is(Types.JSON));\n        final String fifthName = concrete.getProperties().get(\"array\").getName();\n        assertThat(concrete.getProperties().get(\"array\").getType(), is(Types.JSON));\n\n        concrete = getRepresentation(fourthName);\n        assertThat(concrete.getIdentifier().getName(), is(fourthName));\n        assertThat(concrete.getProperties().get(\"string\").getType(), is(Types.STRING));\n\n        collection = getRepresentation(fifthName);\n        assertThat(collection.getIdentifier().getName(), is(fifthName));\n        assertThat(collection.getComponentType().getType(), is(Types.STRING));\n    }\n\n    @Test\n    public void testEqualTypes() {\n        // should be ignored\n        typeRepresentations.put(STRING_LIST_IDENTIFIER, TypeRepresentation.ofCollection(STRING_LIST_IDENTIFIER, TypeRepresentation.ofConcrete(STRING_IDENTIFIER)));\n        final TypeIdentifier modelIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.Model\");\n        final Map<String, TypeIdentifier> modelProperties = Collections.singletonMap(\"string\", TypeUtils.STRING_IDENTIFIER);\n        typeRepresentations.put(modelIdentifier, TypeRepresentation.ofConcrete(modelIdentifier, modelProperties));\n\n        TypeIdentifier identifier = cut.analyze(Json.createArrayBuilder().add(\"foobar\").build());\n        final String firstName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        identifier = cut.analyze(Json.createObjectBuilder().add(\"key\", 0).add(\"object\", Json.createObjectBuilder().add(\"string\", \"value\"))\n                .add(\"array\", Json.createArrayBuilder().add(\"string\")).add(\"other\", Json.createObjectBuilder().add(\"hello\", \"world\")).build());\n        final String secondName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        identifier = cut.analyze(Json.createObjectBuilder().add(\"string\", \"world\").build());\n        final String thirdName = identifier.getName();\n        assertThat(identifier.getType(), is(Types.JSON));\n\n        assertThat(typeRepresentations.size(), is(6));\n\n        TypeRepresentation.CollectionTypeRepresentation collection = getRepresentation(firstName);\n        assertThat(collection.getIdentifier().getName(), is(firstName));\n        assertThat(collection.getComponentType().getType(), is(Types.STRING));\n\n        TypeRepresentation.ConcreteTypeRepresentation concrete = getRepresentation(secondName);\n        assertThat(concrete.getIdentifier().getName(), is(secondName));\n        assertThat(concrete.getProperties().size(), is(4));\n        assertThat(concrete.getProperties().get(\"key\").getType(), is(Types.DOUBLE));\n        assertThat(concrete.getProperties().get(\"object\").getName(), is(thirdName));\n        assertThat(concrete.getProperties().get(\"object\").getType(), is(Types.JSON));\n        assertThat(concrete.getProperties().get(\"array\").getName(), is(firstName));\n        assertThat(concrete.getProperties().get(\"array\").getType(), is(Types.JSON));\n        final String fourthName = concrete.getProperties().get(\"other\").getName();\n        assertThat(concrete.getProperties().get(\"other\").getType(), is(Types.JSON));\n\n        concrete = getRepresentation(thirdName);\n        assertThat(concrete.getIdentifier().getName(), is(thirdName));\n        assertThat(concrete.getProperties().get(\"string\").getType(), is(Types.STRING));\n\n        concrete = getRepresentation(fourthName);\n        assertThat(concrete.getIdentifier().getName(), is(fourthName));\n        assertThat(concrete.getProperties().get(\"hello\").getType(), is(Types.STRING));\n    }\n\n    private <T extends TypeRepresentation> T getRepresentation(final String firstName) {\n        return (T) typeRepresentations.entrySet().stream().filter(e -> e.getKey().getName().equals(firstName)).findAny().get().getValue();\n    }\n\n    private static JsonNumber jsonNumber(final double number) {\n        return Json.createObjectBuilder().add(\"number\", number).build().getJsonNumber(\"number\");\n    }\n\n    private static JsonString jsonString(final String string) {\n        return Json.createObjectBuilder().add(\"string\", string).build().getJsonString(\"string\");\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/JavaTypeAnalyzerTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport javax.ws.rs.NotFoundException;\nimport java.io.IOException;\nimport java.util.*;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\n@RunWith(Parameterized.class)\npublic class JavaTypeAnalyzerTest {\n\n    private final JavaTypeAnalyzer classUnderTest;\n    private final TypeIdentifier expectedIdentifier;\n    private final Set<TypeRepresentation> expectedRepresentations;\n    private final String testClassSimpleName;\n    private final String testClassName;\n    private final Map<TypeIdentifier, TypeRepresentation> actualTypeRepresentations;\n\n    public JavaTypeAnalyzerTest(final String testClassSimpleName, final String testClassName, final TypeIdentifier expectedIdentifier,\n                                final Set<TypeRepresentation> expectedRepresentations) throws NotFoundException {\n        actualTypeRepresentations = new HashMap<>();\n        this.testClassSimpleName = testClassSimpleName;\n        this.testClassName = testClassName;\n        this.expectedIdentifier = expectedIdentifier;\n        this.expectedRepresentations = expectedRepresentations;\n        this.classUnderTest = new JavaTypeAnalyzer(actualTypeRepresentations);\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException {\n        Collection<Object[]> data = new LinkedList<>();\n\n        final Set<String> testClasses = TestClassUtils.getClasses(\"com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer\");\n\n        for (final String testClass : testClasses) {\n            if (!testClass.contains(\"/TestClass\"))\n                continue;\n\n            final Object[] testData = new Object[4];\n            final Class<?> loadedClass = JavaUtils.loadClassFromName(testClass);\n            testData[0] = testClass.substring(testClass.lastIndexOf('/') + 1);\n            testData[1] = testClass;\n            testData[2] = loadedClass.getDeclaredMethod(\"expectedIdentifier\").invoke(null);\n            testData[3] = loadedClass.getDeclaredMethod(\"expectedTypeRepresentations\").invoke(null);\n\n            data.add(testData);\n        }\n\n        return data;\n    }\n\n    @Test\n    public void test() {\n        final TypeIdentifier actualIdentifier;\n        try {\n            actualIdentifier = classUnderTest.analyze(JavaUtils.toType(testClassName));\n        } catch (Exception e) {\n            System.err.println(\"failed for \" + testClassSimpleName);\n            throw e;\n        }\n\n        assertEquals(\"failed for \" + testClassSimpleName, expectedIdentifier, actualIdentifier);\n\n        final Map<TypeIdentifier, TypeRepresentation> expectedTypeRepresentations = expectedRepresentations.stream()\n                .collect(HashMap::new, (m, r) -> m.put(r.getIdentifier(), r), Map::putAll);\n        assertEquals(\"failed for \" + testClassSimpleName, expectedTypeRepresentations, actualTypeRepresentations);\n\n        expectedRepresentations.stream().forEach(ex -> {\n            final TypeRepresentation ac = actualTypeRepresentations.get(ex.getIdentifier());\n            if (!TypeUtils.equals(ex, ac))\n                fail(\"failed for \" + testClassSimpleName + \"\\nNo type representation match \\nexpected: \" + ex + \"\\nactual:   \" + ac);\n        });\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/PathNormalizerTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ClassResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.HttpResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.MethodResultBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Collection;\n\nimport static java.util.Arrays.asList;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(Parameterized.class)\npublic class PathNormalizerTest {\n\n    @Parameterized.Parameter\n    public String path;\n    @Parameterized.Parameter(1)\n    public String methodPath;\n    @Parameterized.Parameter(2)\n    public String nestedMethodPath;\n    @Parameterized.Parameter(3)\n    public String expectedPath;\n\n    @Test\n    public void test() {\n        final ClassResult classResults = buildClassStructure(path, methodPath, nestedMethodPath);\n        final MethodResult methodResult = findDeepestMethodResult(classResults);\n\n        assertThat(PathNormalizer.getPath(methodResult), is(expectedPath));\n    }\n\n    @Parameterized.Parameters(name = \"{0}, {1}, {2} -> {3}\")\n    public static Collection<Object[]> testData() {\n        return asList(\n                new Object[]{\"/test\", \"world\", \"path\", \"test/world/path\"},\n                new Object[]{\"/\", \"/world\", \"path\", \"world/path\"},\n                new Object[]{\"//hello\", \"world\", \"path\", \"hello/world/path\"},\n                new Object[]{\"test\", \"hello\", \"{world}\", \"test/hello/{world}\"},\n                new Object[]{\"test\", \"hello\", \"{world:[foobar]+}\", \"test/hello/{world}\"},\n                new Object[]{\"test\", \"hello\", \"{world:[a-z]+}\", \"test/hello/{world}\"},\n                new Object[]{\"test\", \"hello\", \"hello/world/{world:[a-z]+}-{id}\", \"test/hello/hello/world/{world}-{id}\"},\n                new Object[]{\"//test\", \"hello\", \"/hello/world/{world:[a-z]+}-{id}\", \"test/hello/hello/world/{world}-{id}\"},\n                new Object[]{\"test\", \"hello\", \"hello/{world:[^\\\\{\\\\}a-z]+}-{id}\", \"test/hello/hello/{world}-{id}\"},\n                new Object[]{\"test\", \"hello\", \"{world:.*}\", \"test/hello/{world}\"},\n                new Object[]{\"test\", \"hello\", \"{world:.*}-{id}//\", \"test/hello/{world}-{id}\"},\n                new Object[]{\"test\", \"hello\", \"///{world:.*}-{id}//\", \"test/hello/{world}-{id}\"},\n                new Object[]{\"test\", \"hello\", \"///{world:.*}/-{id}//\", \"test/hello/{world}/-{id}\"},\n                new Object[]{\"test\", \"hello\", \"{world:.*}-{id}/a//\", \"test/hello/{world}-{id}/a\"}\n        );\n    }\n\n    private static ClassResult buildClassStructure(final String path, final String methodPath, final String nestedMethodPath) {\n        final MethodResult nestedMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(204).build()).andPath(nestedMethodPath).andMethod(HttpMethod.POST).build();\n        final ClassResult nestedClassResult = ClassResultBuilder.withResourcePath(\"ignored\").andMethods(nestedMethod).build();\n        final MethodResult method = MethodResultBuilder.newBuilder().andPath(methodPath).build();\n        method.setSubResource(nestedClassResult);\n        return ClassResultBuilder.withResourcePath(path).andMethods(method).build();\n    }\n\n    private static MethodResult findDeepestMethodResult(final ClassResult classResults) {\n        ClassResult current = classResults;\n        MethodResult result = null;\n        while (current != null && !current.getMethods().isEmpty()) {\n            result = current.getMethods().iterator().next();\n            current = result.getSubResource();\n        }\n\n        return result;\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/ResultInterpreterTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.builder.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.STRING_IDENTIFIER;\nimport static org.junit.Assert.assertEquals;\n\npublic class ResultInterpreterTest {\n\n    private ResultInterpreter classUnderTest;\n\n    @Before\n    public void setUp() {\n        classUnderTest = new ResultInterpreter();\n    }\n\n    @Test\n    public void testStandard() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path/\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).build())\n                .andMethod(HttpMethod.GET).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testSubResource() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n        final ResourceMethod resourcePostMethod = ResourceMethodBuilder.withMethod(HttpMethod.POST)\n                .andResponse(204, ResponseBuilder.newBuilder().build()).build();\n        expectedResult.addMethod(\"test/sub\", resourcePostMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"/path\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).build())\n                .andMethod(HttpMethod.GET).build();\n        final MethodResult subResourceLocator = MethodResultBuilder.newBuilder().andPath(\"/sub\").build();\n        final MethodResult subResourceMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(204).build()).andMethod(HttpMethod.POST).build();\n        subResourceLocator.setSubResource(ClassResultBuilder.withResourcePath(null).andMethods(subResourceMethod).build());\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"/test\").andMethods(method, subResourceLocator).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testRootResource() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourcePostMethod = ResourceMethodBuilder.withMethod(HttpMethod.POST)\n                .andResponse(204, ResponseBuilder.newBuilder().build()).build();\n        expectedResult.addMethod(\"test\", resourcePostMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult subResourceMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(204).build()).andPath(\"/test\").andMethod(HttpMethod.POST).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"/\").andMethods(subResourceMethod).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testNormalizeGenericEntityNoCollection() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(\"Ljavax/ws/rs/core/GenericEntity<Ljava/lang/String;>;\").build())\n                .andMethod(HttpMethod.GET).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testContentTypes() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .andResponseMediaTypes(\"application/xml\").build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).build())\n                .andMethod(HttpMethod.GET).andResponseMediaTypes(\"application/xml\").build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testOverrideAnnotationContentType() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .andResponseMediaTypes(\"application/json\").build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andContentTypes(\"application/json\")\n                .andEntityTypes(Types.STRING).build())\n                .andMethod(HttpMethod.GET).andResponseMediaTypes(\"application/xml\", \"application/json\").build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testNestedBasePath() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path/nested\");\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .andResponseMediaTypes(\"application/json\").build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path/nested\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).build())\n                .andMethod(HttpMethod.GET).andResponseMediaTypes(\"application/json\").build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testDefaultStatusCodes() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .andResponseMediaTypes(\"application/json\").build();\n        final ResourceMethod resourcePostMethod = ResourceMethodBuilder.withMethod(HttpMethod.POST).andResponse(204, ResponseBuilder.newBuilder().build())\n                .andRequestBodyType(Types.STRING).build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n        expectedResult.addMethod(\"test\", resourcePostMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult getMethod = MethodResultBuilder.withResponses(HttpResponseBuilder.newBuilder().andEntityTypes(Types.STRING).build())\n                .andResponseMediaTypes(\"application/json\")\n                .andMethod(HttpMethod.GET).andResponseMediaTypes(\"application/json\").build();\n        final MethodResult postMethod = MethodResultBuilder.newBuilder().andMethod(HttpMethod.POST).andRequestBodyType(Types.STRING).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(getMethod, postMethod).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testNormalize() {\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n\n        final TypeIdentifier stringListIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/String;>;\");\n        final TypeRepresentation stringList = TypeRepresentation.ofCollection(stringListIdentifier, TypeRepresentation.ofConcrete(STRING_IDENTIFIER));\n        expectedResult.getTypeRepresentations().put(stringListIdentifier, stringList);\n\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(stringListIdentifier).build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(\"Ljavax/ws/rs/core/GenericEntity<Ljava/util/List<Ljava/lang/String;>;>;\").build())\n                .andMethod(HttpMethod.GET).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testAmbiguousEntityTypes() {\n        final String configurationType = \"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/ResultInterpreterTest$ConfigurationManager$Configuration;\";\n\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final TypeIdentifier identifier = TypeIdentifier.ofType(configurationType);\n        expectedResult.getTypeRepresentations().put(identifier, TypeRepresentation.ofConcrete(identifier,\n                Collections.singletonMap(\"name\", STRING_IDENTIFIER)));\n\n        final ResourceMethod resourceGetMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build())\n                .andResponse(204, ResponseBuilder.newBuilder().build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceGetMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path\").build();\n        final MethodResult method = MethodResultBuilder\n                .withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.OBJECT, configurationType).build(),\n                        HttpResponseBuilder.withStatues(204).build())\n                .andMethod(HttpMethod.GET).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    @Test\n    public void testDescriptions() {\n        final MethodComment methodDoc = new MethodComment(\"Method description.\");\n\n        final Resources expectedResult = new Resources();\n        expectedResult.setBasePath(\"path\");\n        final ResourceMethod resourceMethod = ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Method description.\")\n                .andQueryParam(\"query\", \"Ljava/lang/String;\", null)\n                .andResponse(200, ResponseBuilder.withResponseBody(STRING_IDENTIFIER).build())\n                .build();\n        expectedResult.addMethod(\"test\", resourceMethod);\n\n        final ClassResult appPathResult = ClassResultBuilder.withApplicationPath(\"path/\").build();\n        final MethodResult method = MethodResultBuilder.withResponses(HttpResponseBuilder.withStatues(200).andEntityTypes(Types.STRING).build())\n                .andMethodDoc(methodDoc)\n                .andQueryParam(\"query\", \"Ljava/lang/String;\", null)\n                .andMethod(HttpMethod.GET).build();\n        final ClassResult resClassResult = ClassResultBuilder.withResourcePath(\"test\").andMethods(method).build();\n\n        final Set<ClassResult> results = new HashSet<>(Arrays.asList(appPathResult, resClassResult));\n\n        final Resources actualResult = classUnderTest.interpret(results);\n\n        assertEquals(expectedResult, actualResult);\n    }\n\n    private interface ConfigurationManager {\n        @XmlAccessorType(XmlAccessType.FIELD)\n        class Configuration {\n            private String name;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/TypeUtils.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\npublic final class TypeUtils {\n\n    public static final TypeIdentifier OBJECT_IDENTIFIER = TypeIdentifier.ofType(Types.OBJECT);\n    public static final TypeIdentifier STRING_IDENTIFIER = TypeIdentifier.ofType(Types.STRING);\n    public static final TypeIdentifier INT_IDENTIFIER = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n    public static final TypeIdentifier STRING_LIST_IDENTIFIER = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/String;>;\");\n    public static final TypeIdentifier MODEL_IDENTIFIER = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/Model;\");\n    public static final TypeIdentifier ENUM_IDENTIFIER = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/Enumeration;\");\n\n    private TypeUtils() {\n        throw new UnsupportedOperationException();\n    }\n\n    /**\n     * Checks if the first representation fully equals to the second, i.e. the identifier has to be the same as well as the contained element\n     * (for collections) or the properties (for concrete types).\n     */\n    public static boolean equals(final TypeRepresentation first, final TypeRepresentation second) {\n        if (!first.equals(second))\n            return false;\n\n        final boolean firstCollection = first instanceof TypeRepresentation.CollectionTypeRepresentation;\n        final boolean secondCollection = second instanceof TypeRepresentation.CollectionTypeRepresentation;\n\n        if (firstCollection ^ secondCollection)\n            return false;\n\n        if (firstCollection)\n            return ((TypeRepresentation.CollectionTypeRepresentation) first).contentEquals(((TypeRepresentation.CollectionTypeRepresentation) second).getRepresentation());\n\n        final boolean firstEnum = first instanceof TypeRepresentation.EnumTypeRepresentation;\n        final boolean secondEnum = second instanceof TypeRepresentation.EnumTypeRepresentation;\n\n        if (firstEnum ^ secondEnum)\n            return false;\n\n        if (firstEnum) {\n            final TypeRepresentation.EnumTypeRepresentation firstEnumRep = (TypeRepresentation.EnumTypeRepresentation) first;\n            final TypeRepresentation.EnumTypeRepresentation secondEnumRep = (TypeRepresentation.EnumTypeRepresentation) second;\n            return firstEnumRep.getEnumValues().equals(secondEnumRep.getEnumValues()) && firstEnumRep.getComponentType().equals(secondEnumRep.getComponentType());\n        }\n\n        return ((TypeRepresentation.ConcreteTypeRepresentation) first).contentEquals(((TypeRepresentation.ConcreteTypeRepresentation) second).getProperties());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass1.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass1 {\n\n    private static String PRIVATE_FIELD;\n    public static String PUBLIC_FIELD;\n    private String privateField;\n    protected String protectedField;\n    public String publicField;\n\n    public String getTest() {\n        return null;\n    }\n\n    public int getInt() {\n        return 0;\n    }\n\n    public static String getStaticString() {\n        return null;\n    }\n\n    public String string() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"publicField\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"int\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass1;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass10.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass10 {\n\n    private boolean first;\n    private Map second;\n    private Map<String, String> third;\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public Map getSecond() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n        properties.put(\"second\", TypeIdentifier.ofType(\"Ljava/util/Map;\"));\n        properties.put(\"third\", TypeIdentifier.ofType(\"Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>;\"));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass10;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass11.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass11 {\n\n    private boolean first;\n    private int second;\n    private TestClass11 child;\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier identifier = expectedIdentifier();\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n        properties.put(\"second\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n        properties.put(\"child\", identifier);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(identifier, properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass11;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass12.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.*;\n\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass12 {\n\n    private int first;\n    private InnerTestClass child;\n\n    @XmlAccessorType(XmlAccessType.FIELD)\n    private class InnerTestClass {\n        private int second;\n        private TestClass12 child;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier innerTestIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass12$InnerTestClass;\");\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n        properties.put(\"child\", innerTestIdentifier);\n\n        final TypeIdentifier testClass12Identifier = expectedIdentifier();\n        final TypeRepresentation testClass12 = TypeRepresentation.ofConcrete(testClass12Identifier, properties);\n\n        final Map<String, TypeIdentifier> innerProperties = new HashMap<>();\n        innerProperties.put(\"second\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n        innerProperties.put(\"child\", testClass12Identifier);\n\n        final TypeRepresentation innerTestClass = TypeRepresentation.ofConcrete(innerTestIdentifier, innerProperties);\n\n        return new HashSet<>(Arrays.asList(testClass12, innerTestClass));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass12;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass13.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.*;\n\npublic class TestClass13 {\n\n    private GenericFields<Long, String> longAndString;\n    private GenericFields<String, Long> stringAndLong;\n\n    public GenericFields<Long, String> getLongAndString() {\n        return longAndString;\n    }\n\n    public GenericFields<String, Long> getStringAndLong() {\n        return stringAndLong;\n    }\n\n    private static class GenericFields<A, B> {\n\n        private A a;\n\n        private B b;\n\n        private List<A> listA;\n\n        public A getA() {\n            return a;\n        }\n\n        public B getB() {\n            return b;\n        }\n\n        public List<A> getListA() {\n            return listA;\n        }\n\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier longStringIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass13$GenericFields<Ljava/lang/Long;Ljava/lang/String;>;\");\n        final TypeIdentifier stringLongIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass13$GenericFields<Ljava/lang/String;Ljava/lang/Long;>;\");\n        final TypeIdentifier stringIdentifier = TypeUtils.STRING_IDENTIFIER;\n        final TypeIdentifier longIdentifier = TypeIdentifier.ofType(Types.LONG);\n\n        properties.put(\"longAndString\", longStringIdentifier);\n        properties.put(\"stringAndLong\", stringLongIdentifier);\n\n        final TypeRepresentation testClass13 = TypeRepresentation.ofConcrete(expectedIdentifier(), properties);\n\n        final TypeIdentifier listStringIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/String;>;\");\n        final TypeRepresentation listString = TypeRepresentation.ofCollection(listStringIdentifier, TypeRepresentation.ofConcrete(stringIdentifier));\n        final TypeIdentifier listLongIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/Long;>;\");\n        final TypeRepresentation listLong = TypeRepresentation.ofCollection(listLongIdentifier, TypeRepresentation.ofConcrete(longIdentifier));\n\n        final Map<String, TypeIdentifier> longStringProperties = new HashMap<>();\n        longStringProperties.put(\"a\", longIdentifier);\n        longStringProperties.put(\"b\", stringIdentifier);\n        longStringProperties.put(\"listA\", listLongIdentifier);\n        final TypeRepresentation longString = TypeRepresentation.ofConcrete(longStringIdentifier, longStringProperties);\n\n        final Map<String, TypeIdentifier> stringLongProperties = new HashMap<>();\n        stringLongProperties.put(\"a\", stringIdentifier);\n        stringLongProperties.put(\"b\", longIdentifier);\n        stringLongProperties.put(\"listA\", listStringIdentifier);\n        final TypeRepresentation stringLong = TypeRepresentation.ofConcrete(stringLongIdentifier, stringLongProperties);\n\n        return new HashSet<>(Arrays.asList(testClass13, longString, stringLong, listLong, listString));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass13;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass14.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.*;\n\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass14 {\n\n    private GenericFields<Long, String> longAndString;\n    private GenericFields<String, Long> stringAndLong;\n\n    public GenericFields<Long, String> getLongAndString() {\n        return longAndString;\n    }\n\n    public GenericFields<String, Long> getStringAndLong() {\n        return stringAndLong;\n    }\n\n    @XmlAccessorType(XmlAccessType.FIELD)\n    private static class GenericFields<A, B> {\n\n        private A a;\n\n        private B b;\n\n        private List<A> listA;\n\n        public A getA() {\n            return a;\n        }\n\n        public B getB() {\n            return b;\n        }\n\n        public List<A> getListA() {\n            return listA;\n        }\n\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier longStringIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass14$GenericFields<Ljava/lang/Long;Ljava/lang/String;>;\");\n        final TypeIdentifier stringLongIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass14$GenericFields<Ljava/lang/String;Ljava/lang/Long;>;\");\n        final TypeIdentifier stringIdentifier = TypeUtils.STRING_IDENTIFIER;\n        final TypeIdentifier longIdentifier = TypeIdentifier.ofType(Types.LONG);\n\n        properties.put(\"longAndString\", longStringIdentifier);\n        properties.put(\"stringAndLong\", stringLongIdentifier);\n\n        final TypeRepresentation testClass13 = TypeRepresentation.ofConcrete(expectedIdentifier(), properties);\n\n        final TypeIdentifier listStringIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/String;>;\");\n        final TypeRepresentation listString = TypeRepresentation.ofCollection(listStringIdentifier, TypeRepresentation.ofConcrete(stringIdentifier));\n        final TypeIdentifier listLongIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/Long;>;\");\n        final TypeRepresentation listLong = TypeRepresentation.ofCollection(listLongIdentifier, TypeRepresentation.ofConcrete(longIdentifier));\n\n        final Map<String, TypeIdentifier> longStringProperties = new HashMap<>();\n        longStringProperties.put(\"a\", longIdentifier);\n        longStringProperties.put(\"b\", stringIdentifier);\n        longStringProperties.put(\"listA\", listLongIdentifier);\n        final TypeRepresentation longString = TypeRepresentation.ofConcrete(longStringIdentifier, longStringProperties);\n\n        final Map<String, TypeIdentifier> stringLongProperties = new HashMap<>();\n        stringLongProperties.put(\"a\", stringIdentifier);\n        stringLongProperties.put(\"b\", longIdentifier);\n        stringLongProperties.put(\"listA\", listStringIdentifier);\n        final TypeRepresentation stringLong = TypeRepresentation.ofConcrete(stringLongIdentifier, stringLongProperties);\n\n        return new HashSet<>(Arrays.asList(testClass13, longString, stringLong, listLong, listString));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass14;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass15.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass15 extends SuperTestClass1 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass15;\");\n    }\n\n}\n\nclass SuperTestClass1 {\n\n    private String test;\n\n    public String getTest() {\n        return test;\n    }\n\n    public void setTest(String test) {\n        this.test = test;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass16.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.*;\n\npublic class TestClass16 extends SuperTestClass2 {\n\n    private String world;\n    private SuperTestClass2 partner;\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier superTestClass2 = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/SuperTestClass2;\");\n        final TypeIdentifier stringIdentifier = TypeUtils.STRING_IDENTIFIER;\n        properties.put(\"hello\", stringIdentifier);\n        properties.put(\"world\", stringIdentifier);\n        properties.put(\"partner\", superTestClass2);\n\n        return new HashSet<>(Arrays.asList(TypeRepresentation.ofConcrete(expectedIdentifier(), properties),\n                TypeRepresentation.ofConcrete(superTestClass2, Collections.singletonMap(\"hello\", stringIdentifier))));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass16;\");\n    }\n\n}\n\n@XmlAccessorType(XmlAccessType.FIELD)\nclass SuperTestClass2 {\n    private String hello;\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass17.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.*;\n\npublic class TestClass17 extends SuperTestClass3 {\n\n    private String world;\n    private SuperTestClass3 partner;\n\n    public String getWorld() {\n        return world;\n    }\n\n    public void setWorld(String world) {\n        this.world = world;\n    }\n\n    public SuperTestClass3 getPartner() {\n        return partner;\n    }\n\n    public void setPartner(SuperTestClass3 partner) {\n        this.partner = partner;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier superTestClass3 = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/SuperTestClass3;\");\n        final TypeIdentifier stringIdentifier = TypeUtils.STRING_IDENTIFIER;\n        properties.put(\"hello\", stringIdentifier);\n        properties.put(\"world\", stringIdentifier);\n        properties.put(\"partner\", superTestClass3);\n\n        return new HashSet<>(Arrays.asList(TypeRepresentation.ofConcrete(expectedIdentifier(), properties),\n                TypeRepresentation.ofConcrete(superTestClass3, Collections.singletonMap(\"hello\", stringIdentifier))));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass17;\");\n    }\n\n}\n\nclass SuperTestClass3 {\n    private String hello;\n\n    public String getHello() {\n        return hello;\n    }\n\n    public void setHello(String hello) {\n        this.hello = hello;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass18.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n// TODO remove\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass18 extends SuperTestClass4 {\n\n    private String foobar;\n    private TestClass18 partner;\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier identifier = expectedIdentifier();\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"partner\", identifier);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(identifier, properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass18;\");\n    }\n\n}\n\n@XmlAccessorType(XmlAccessType.FIELD)\nclass SuperTestClass4 {\n    private String test;\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass19.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass19 extends SuperTestClass5 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"hello\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"overidden\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass19;\");\n    }\n\n}\n\nclass SuperTestClass5 extends SuperTestClass6 {\n\n    private String test;\n\n    public String getTest() {\n        return test;\n    }\n\n    public void setTest(String test) {\n        this.test = test;\n    }\n\n    public String getOveridden() {\n        return \"Overidden return value\";\n    }\n\n}\n\nabstract class SuperTestClass6 {\n\n    private String hello;\n\n    public String getHello() {\n        return hello;\n    }\n\n    public void setHello(String hello) {\n        this.hello = hello;\n    }\n\n    public abstract Object getOveridden();\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass2.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlTransient;\nimport java.util.Collections;\nimport java.util.Set;\n\npublic class TestClass2 {\n\n    private String first;\n\n    @XmlTransient // ignored due to XMLAccessorTypes#PUBLIC_MEMBER\n    private String second;\n\n    @XmlTransient\n    public String third;\n\n    @XmlTransient\n    public String getFirst() {\n        return first;\n    }\n\n    public String getSecond() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), Collections.singletonMap(\"second\", TypeUtils.STRING_IDENTIFIER)));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass2;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass20.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass20 implements Interface1, Interface2 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test1\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test2\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test3\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"test4\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass20;\");\n    }\n\n    @Override\n    public String getTest1() {\n        return null;\n    }\n\n    @Override\n    public String getTest2() {\n        return null;\n    }\n}\n\ninterface Interface1 {\n\n    String getTest1();\n\n}\n\ninterface Interface2 extends Interface3 {\n\n    String getTest2();\n\n    default String getTest3() {\n        return \"string default\";\n    }\n}\n\ninterface Interface3 {\n\n    Object getTest3();\n\n    default String getTest4() {\n        return \"default\";\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass21.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static java.util.Arrays.asList;\n\npublic class TestClass21 {\n\n    private InnerTestClass21 inner;\n\n    public InnerTestClass21 getInner() {\n        return inner;\n    }\n\n    public void setInner(final InnerTestClass21 inner) {\n        this.inner = inner;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier inner = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass21$InnerTestClass21;\");\n        properties.put(\"inner\", inner);\n\n        return new HashSet<>(asList(TypeRepresentation.ofConcrete(expectedIdentifier(), properties), TypeRepresentation.ofEnum(inner, \"FIRST\", \"SECOND\")));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass21;\");\n    }\n\n    private enum InnerTestClass21 {\n        FIRST, SECOND\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass22.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Test @JsonIgnore on primitive field\n */\npublic class TestClass22 {\n\n    private static String PRIVATE_FIELD;\n    public static String PUBLIC_FIELD;\n    private String privateField;\n    protected String protectedField;\n    @JsonIgnore\n    public String publicField;\n\n    public String getTest() {\n        return null;\n    }\n\n    public int getInt() {\n        return 0;\n    }\n\n    public static String getStaticString() {\n        return null;\n    }\n\n    public String string() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n\n        // properties.put(\"publicField\", TypeUtils.STRING_IDENTIFIER); //ignored by @JsonIgnore\n        properties.put(\"test\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"int\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass22;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass23.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Test @JsonIgnore on type field\n */\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass23 {\n\n    private boolean first;\n    private int second;\n    @JsonIgnore\n    private TestClass23 child;\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier identifier = expectedIdentifier();\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n        properties.put(\"second\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n        //properties.put(\"child\", identifier); @JsonIgnore\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(identifier, properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass23;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass24.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport java.util.*;\n\n/**\n * Test @JsonIgnoreType\n */\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass24 {\n\n    private int first;\n    private InnerTestClass child;\n\n    @JsonIgnoreType\n    private class InnerTestClass {\n        private int second;\n        private TestClass24 child;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n\n        final TypeIdentifier testClass24Identifier = expectedIdentifier();\n        final TypeRepresentation testClass24 = TypeRepresentation.ofConcrete(testClass24Identifier, properties);\n\n\n        return new HashSet<>(Arrays.asList(testClass24));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass24;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass25.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Test @JsonIgnore at method level\n */\npublic class TestClass25 {\n\n    private static String PRIVATE_FIELD;\n    public static String PUBLIC_FIELD;\n    private String privateField;\n    protected String protectedField;\n\n    public String publicField;\n\n    @JsonIgnore\n    public String getTest() {\n        return null;\n    }\n\n    public int getInt() {\n        return 0;\n    }\n\n    public static String getStaticString() {\n        return null;\n    }\n\n    public String string() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n\n        properties.put(\"publicField\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"int\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass25;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass26.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @JsonIgnore in superclass\n */\npublic class TestClass26 extends SuperTestClass26 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass26;\");\n    }\n\n}\n\n\nclass SuperTestClass26 {\n\n    @JsonIgnore\n    private String test;\n\n    public String getTest() {\n        return test;\n    }\n\n    public void setTest(String test) {\n        this.test = test;\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass27.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\n/**\n * Created by rafael-pestano on 02/01/17.\n */\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreType;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @JsonIgnoreType in superclass\n */\npublic class TestClass27 extends SuperTestClass27 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass27;\");\n    }\n\n}\n\n@JsonIgnoreType\nclass SuperTestClass27 {\n\n    private String test;\n\n    public String getTest() {\n        return test;\n    }\n\n    public void setTest(String test) {\n        this.test = test;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass28.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @JsonIgnore in superclass method\n */\npublic class TestClass28 extends SuperTestClass28 {\n\n    private String foobar;\n\n    public String getFoobar() {\n        return foobar;\n    }\n\n    public void setFoobar(String foobar) {\n        this.foobar = foobar;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"foobar\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass28;\");\n    }\n\n}\n\n\nclass SuperTestClass28 {\n\n    private String test;\n\n    @JsonIgnore\n    public String getTest() {\n        return test;\n    }\n\n    public void setTest(String test) {\n        this.test = test;\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass29.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Test @JsonIgnore with boolean getter\n */\npublic class TestClass29 {\n\n    private static String PRIVATE_FIELD;\n    public static String PUBLIC_FIELD;\n    private String privateField;\n    protected String protectedField;\n\n    public String publicField;\n\n    @JsonIgnore\n    private boolean test;\n\n    public boolean isTest() {\n        return false;\n    }\n\n    public int getInt() {\n        return 0;\n    }\n\n    public static String getStaticString() {\n        return null;\n    }\n\n    public String string() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"publicField\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"int\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass29;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass3.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport javax.xml.bind.annotation.XmlRootElement;\nimport java.util.*;\n\n@XmlRootElement\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass3 {\n\n    private InnerClass first;\n\n    private Type second;\n\n    private AnotherInner third;\n\n    public InnerClass getFirrst() {\n        return first;\n    }\n\n    public Type getSeccond() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier innerClassIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass3$InnerClass;\");\n        final TypeIdentifier typeIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass3$Type;\");\n        final TypeIdentifier anotherInnerIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass3$AnotherInner;\");\n\n        properties.put(\"first\", innerClassIdentifier);\n        properties.put(\"second\", typeIdentifier);\n        properties.put(\"third\", anotherInnerIdentifier);\n\n        final TypeRepresentation testClass3 = TypeRepresentation.ofConcrete(expectedIdentifier(), properties);\n        final TypeRepresentation innerClass = TypeRepresentation.ofConcrete(innerClassIdentifier, Collections.singletonMap(\"name\", TypeUtils.STRING_IDENTIFIER));\n        final TypeRepresentation anotherInner = TypeRepresentation.ofConcrete(anotherInnerIdentifier);\n        final TypeRepresentation type = TypeRepresentation.ofEnum(typeIdentifier, \"ONE\", \"TWO\", \"THREE\");\n\n        return new HashSet<>(Arrays.asList(testClass3, innerClass, anotherInner, type));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass3;\");\n    }\n\n    public AnotherInner getThirrd() {\n        return third;\n    }\n\n    private enum Type {\n        ONE, TWO, THREE\n    }\n\n    private class InnerClass {\n        private String name;\n\n        public String getName() {\n            return name;\n        }\n    }\n\n    private class AnotherInner {\n        private String notUsed;\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass30.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Test @JsonIgnore with several methods & different cases\n */\npublic class TestClass30 {\n\n    private static String PRIVATE_FIELD;\n    public static String PUBLIC_FIELD;\n    private String privateField;\n    protected String protectedField;\n\n    public String publicField;\n\n    @JsonIgnore\n    private boolean testName;\n    private boolean testname;\n\n    public boolean isTestName() {\n        return testName;\n    }\n\n    public boolean isTestname() {\n        return testname;\n    }\n\n    public int getInt() {\n        return 0;\n    }\n\n    public static String getStaticString() {\n        return null;\n    }\n\n    public String string() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"publicField\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"int\", TypeIdentifier.ofType(Types.PRIMITIVE_INT));\n        properties.put(\"testname\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass30;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass4.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.time.LocalDate;\nimport java.util.*;\n\npublic class TestClass4 {\n\n    private LocalDate first;\n\n    private Date second;\n\n    public LocalDate getFirst() {\n        return first;\n    }\n\n    public Date getSecond() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"first\", TypeIdentifier.ofType(\"Ljava/time/LocalDate;\"));\n        properties.put(\"second\", TypeIdentifier.ofType(Types.DATE));\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass4;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass5.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.*;\nimport java.util.*;\n\n@XmlRootElement\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class TestClass5 {\n\n    private List<String> first;\n    private transient String third;\n    @XmlTransient\n    private String fourth;\n\n    public List<String> getIgnored() {\n        return first;\n    }\n\n    @XmlElement\n    public Set<String> getSecond() {\n        return null;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final TypeIdentifier listIdentifier = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/String;>;\");\n        final TypeIdentifier setIdentifier = TypeIdentifier.ofType(\"Ljava/util/Set<Ljava/lang/String;>;\");\n\n        properties.put(\"first\", listIdentifier);\n        properties.put(\"second\", setIdentifier);\n\n        final TypeRepresentation testClass5 = TypeRepresentation.ofConcrete(expectedIdentifier(), properties);\n        final TypeRepresentation string = TypeRepresentation.ofConcrete(TypeUtils.STRING_IDENTIFIER);\n        final TypeRepresentation listString = TypeRepresentation.ofCollection(listIdentifier, string);\n        final TypeRepresentation setString = TypeRepresentation.ofCollection(setIdentifier, string);\n\n        return new HashSet<>(Arrays.asList(testClass5, listString, setString));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass5;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass6.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlElement;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class TestClass6 {\n\n    private boolean first;\n    private String second;\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public String getSecond() {\n        return second;\n    }\n\n    // not taken, wrong return type\n    public void getFake() {\n    }\n\n    public String isFake() {\n        return second;\n    }\n\n    @XmlElement\n    private String getThird() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n        properties.put(\"second\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"third\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass6;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass7.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport javax.xml.bind.annotation.XmlElement;\nimport javax.xml.bind.annotation.XmlRootElement;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n@XmlRootElement\n@XmlAccessorType(XmlAccessType.PROPERTY)\npublic class TestClass7 {\n\n    private boolean firrst;\n    private String seccond;\n    @XmlElement\n    private String third;\n\n    public boolean isFirst() {\n        return firrst;\n    }\n\n    public String getSecond() {\n        return seccond;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"first\", TypeIdentifier.ofType(Types.PRIMITIVE_BOOLEAN));\n        properties.put(\"second\", TypeUtils.STRING_IDENTIFIER);\n        properties.put(\"third\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass7;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass8.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.results.testclasses.typeanalyzer;\n\nimport com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport javax.xml.bind.annotation.XmlAccessType;\nimport javax.xml.bind.annotation.XmlAccessorType;\nimport javax.xml.bind.annotation.XmlElement;\nimport javax.xml.bind.annotation.XmlRootElement;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n@XmlRootElement\n@XmlAccessorType(XmlAccessType.NONE)\npublic class TestClass8 {\n\n    private boolean first;\n    private String second;\n    @XmlElement\n    private String third;\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public String getSecond() {\n        return second;\n    }\n\n    public static Set<TypeRepresentation> expectedTypeRepresentations() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"third\", TypeUtils.STRING_IDENTIFIER);\n\n        return Collections.singleton(TypeRepresentation.ofConcrete(expectedIdentifier(), properties));\n    }\n\n    public static TypeIdentifier expectedIdentifier() {\n        return TypeIdentifier.ofType(\"Lcom/sebastian_daschner/jaxrs_analyzer/analysis/results/testclasses/typeanalyzer/TestClass8;\");\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/utils/JavaUtilSignatureTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.utils;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static java.util.Arrays.asList;\nimport static java.util.Collections.singletonList;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(Parameterized.class)\npublic class JavaUtilSignatureTest {\n\n    private final String signature;\n    private final List<String> parameterTypes;\n\n    public JavaUtilSignatureTest(final String signature, final List<String> parameterTypes) {\n        this.signature = signature;\n        this.parameterTypes = parameterTypes;\n    }\n\n    @Test\n    public void testGetParameters() {\n        try {\n            assertThat(JavaUtils.getParameters(signature), is(parameterTypes));\n        } catch (Exception e) {\n            System.err.println(\"Failed for \" + signature);\n            throw e;\n        }\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        final Collection<Object[]> data = new LinkedList<>();\n\n        data.add(testData(\"(Z)V\", singletonList(\"Z\")));\n        data.add(testData(\"([Z)V\", singletonList(\"[Z\")));\n        data.add(testData(\"(Ljava/lang/String;)V\", singletonList(\"Ljava/lang/String;\")));\n        data.add(testData(\"(Ljava/lang/String;Ljava/util/List;)V\", asList(\"Ljava/lang/String;\", \"Ljava/util/List;\")));\n        data.add(testData(\"(Ljava/util/List<Ljava/lang/String;>;)V\", singletonList(\"Ljava/util/List<Ljava/lang/String;>;\")));\n        data.add(testData(\"([Ljava/util/List<Ljava/lang/String;>;)V\", singletonList(\"[Ljava/util/List<Ljava/lang/String;>;\")));\n        data.add(testData(\"(Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>;)Ljavax/ws/rs/core/Response;\",\n                singletonList(\"Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>;\")));\n        data.add(testData(\"([Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>;)Ljavax/ws/rs/core/Response;\",\n                singletonList(\"[Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>;\")));\n\n        return data;\n    }\n\n    private static Object[] testData(String signature, List<String> types) {\n        final Object[] testData = new Object[2];\n        testData[0] = signature;\n        testData[1] = types;\n        return testData;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/utils/JavaUtilsTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.analysis.utils;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport org.junit.Test;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.*;\nimport static org.hamcrest.CoreMatchers.hasItems;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.*;\n\npublic class JavaUtilsTest {\n\n    @Test\n    public void testGetTypeParameters() {\n        assertThat(getTypeParameters(\"B\").size(), is(0));\n        assertThat(getTypeParameters(\"Z\").size(), is(0));\n        assertThat(getTypeParameters(Types.STRING).size(), is(0));\n        assertThat(getTypeParameters(\"[Ljava/lang/String;\").size(), is(0));\n        assertThat(getTypeParameters(\"Ljava/util/List<Ljava/lang/String;>;\"), hasItems(Types.STRING));\n        assertThat(getTypeParameters(\"Ljava/lang/Map<Ljava/lang/String;Ljava/lang/Integer;>;\"), hasItems(Types.STRING, Types.INTEGER));\n        assertThat(getTypeParameters(\"Ljava/util/List<Ljava/util/List<Ljava/lang/Integer;>;>;\"), hasItems(\"Ljava/util/List<Ljava/lang/Integer;>;\"));\n        assertThat(getTypeParameters(\"Ljava/util/Map<Ljava/util/List<Ljava/lang/Integer;>;Ljava/util/List<Ljava/lang/String;>;>;\"), hasItems(\"Ljava/util/List<Ljava/lang/Integer;>;\", \"Ljava/util/List<Ljava/lang/String;>;\"));\n    }\n\n    @Test\n    public void testIsAssignableToSame() {\n        final String sameType = \"Ljava/lang/Object;\";\n        assertTrue(isAssignableTo(sameType, Types.OBJECT));\n        assertTrue(isAssignableTo(Types.OBJECT, sameType));\n    }\n\n    @Test\n    public void testIsAssignableToPrimitives() {\n        assertFalse(isAssignableTo(Types.PRIMITIVE_INT, Types.OBJECT));\n        assertFalse(isAssignableTo(Types.OBJECT, Types.PRIMITIVE_INT));\n        assertFalse(isAssignableTo(Types.PRIMITIVE_BOOLEAN, Types.PRIMITIVE_INT));\n        assertTrue(isAssignableTo(Types.PRIMITIVE_INT, Types.PRIMITIVE_INT));\n    }\n\n    @Test\n    public void testIsAssignableToArray() {\n        final String intArray = \"[I\";\n        final String objectArray = \"[Ljava/lang/Object;\";\n        final String listArray = \"[Ljava/util/List;\";\n        final String stringListArray = \"[Ljava/util/List<Ljava/lang/String;>\";\n        final String linkedListArray = \"[Ljava/util/LinkedList;\";\n\n        assertFalse(isAssignableTo(intArray, Types.PRIMITIVE_INT));\n        assertFalse(isAssignableTo(Types.PRIMITIVE_INT, intArray));\n        assertFalse(isAssignableTo(objectArray, intArray));\n        assertFalse(isAssignableTo(intArray, objectArray));\n        assertTrue(isAssignableTo(objectArray, objectArray));\n        assertTrue(isAssignableTo(intArray, intArray));\n        assertTrue(isAssignableTo(listArray, stringListArray));\n        assertTrue(isAssignableTo(stringListArray, listArray));\n        assertTrue(isAssignableTo(linkedListArray, listArray));\n        assertFalse(isAssignableTo(listArray, linkedListArray));\n    }\n\n    @Test\n    public void testIsAssignableToInheritance() {\n        final String parentType = \"Ljava/lang/Number;\";\n        final String inheritedType = \"Ljava/lang/Integer;\";\n        assertFalse(isAssignableTo(parentType, inheritedType));\n        assertTrue(isAssignableTo(inheritedType, parentType));\n    }\n\n    @Test\n    public void testIsAssignableToGeneric() {\n        final String parentType = \"Ljava/util/List;\";\n        final String inheritedType = \"Ljava/util/LinkedList;\";\n        assertFalse(isAssignableTo(parentType, inheritedType));\n        assertTrue(isAssignableTo(inheritedType, parentType));\n    }\n\n    @Test\n    public void testIsAssignableToParameterized() {\n        final String parentType = \"Ljava/util/List<Ljava/lang/String;>;\";\n        final String inheritedType = \"Ljava/util/LinkedList<Ljava/lang/String;>;\";\n        assertFalse(isAssignableTo(parentType, inheritedType));\n        assertTrue(isAssignableTo(inheritedType, parentType));\n    }\n\n    @Test\n    public void testIsAssignableToDifferentTypes() {\n        assertFalse(isAssignableTo(Types.STRING, Types.STREAM));\n        assertFalse(isAssignableTo(Types.STREAM, Types.STRING));\n    }\n\n    @Test\n    public void testIsAssignableToParameterizedInheritedParameters() {\n        final String parentType = \"Ljava/util/List<Ljava/lang/Number;>;\";\n        final String inheritedType = \"Ljava/util/List<Ljava/lang/Integer;>;\";\n        assertFalse(isAssignableTo(parentType, inheritedType));\n        assertFalse(isAssignableTo(inheritedType, parentType));\n    }\n\n    @Test\n    public void testIsAssignableToParameterizedInheritedParametersExtended() {\n        final String parentType = \"Ljava/util/List<Ljava/lang/Number;>;\";\n        final String inheritedType = \"Ljava/util/LinkedList<Ljava/lang/Integer;>;\";\n        assertFalse(isAssignableTo(parentType, inheritedType));\n        assertFalse(isAssignableTo(inheritedType, parentType));\n    }\n\n    @Test\n    public void testIsAssignableToCollection() {\n        final String type = \"Ljava/util/List<Ljava/lang/String;>;\";\n        assertFalse(isAssignableTo(Types.COLLECTION, type));\n        assertTrue(isAssignableTo(type, Types.COLLECTION));\n    }\n\n    @Test\n    public void testIsAssignableToOddParameterizedTypes() {\n        final String type = \"Ljava/util/List<Ljava/lang/String;>;\";\n        final String subType = \"Ljava/util/LinkedList<Ljava/lang/String;>;\";\n        final String rawType = \"Ljava/util/List;\";\n        final String rawSubType = \"Ljava/util/LinkedList;\";\n        assertFalse(isAssignableTo(type, subType));\n        assertTrue(isAssignableTo(subType, type));\n        assertTrue(isAssignableTo(type, rawType));\n        assertTrue(isAssignableTo(rawType, type));\n        assertFalse(isAssignableTo(type, rawSubType));\n        assertTrue(isAssignableTo(rawSubType, type));\n        assertTrue(isAssignableTo(subType, rawType));\n        assertFalse(isAssignableTo(rawType, subType));\n        assertTrue(isAssignableTo(subType, rawSubType));\n        assertTrue(isAssignableTo(rawSubType, subType));\n        assertFalse(isAssignableTo(rawType, rawSubType));\n        assertTrue(isAssignableTo(rawSubType, rawType));\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeOnlyOne() {\n        final String actualType = determineMostSpecificType(Types.LIST);\n        assertEquals(Types.LIST, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeParameterized() {\n        final String parameterizedType = \"Ljava/util/List<Ljava/lang/String;>;\";\n\n        String actualType = determineMostSpecificType(Types.LIST, parameterizedType);\n        assertEquals(parameterizedType, actualType);\n\n        actualType = determineMostSpecificType(parameterizedType, Types.LIST);\n        assertEquals(parameterizedType, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeArray() {\n        final String stringArray = \"[Ljava/lang/String;\";\n\n        String actualType = determineMostSpecificType(Types.STRING, stringArray);\n        assertEquals(stringArray, actualType);\n\n        actualType = determineMostSpecificType(stringArray, Types.STRING);\n        assertEquals(stringArray, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeObject() {\n        final String responseType = \"Ljavax/ws/rs/core/Response$Status;\";\n\n        String actualType = determineMostSpecificType(Types.OBJECT, responseType);\n        assertEquals(responseType, actualType);\n\n        actualType = determineMostSpecificType(responseType, Types.OBJECT);\n        assertEquals(responseType, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeInheritance() {\n        final String linkedListType = \"Ljava/util/LinkedList;\";\n\n        String actualType = determineMostSpecificType(Types.LIST, linkedListType);\n        assertEquals(linkedListType, actualType);\n\n        actualType = determineMostSpecificType(linkedListType, Types.LIST);\n        assertEquals(linkedListType, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeParameterizedInner() {\n        final String lockList = \"Ljava/util/List<Ljava/util/concurrent/locks/Lock;>;\";\n        final String stampedLockList = \"Ljava/util/List<Ljava/util/concurrent/locks/ReentrantLock;>;\";\n\n        String actualType = determineMostSpecificType(lockList, stampedLockList);\n        assertEquals(stampedLockList, actualType);\n\n        actualType = determineMostSpecificType(stampedLockList, lockList);\n        assertEquals(stampedLockList, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeParameterizedInheritance() {\n        final String lockList = \"Ljava/util/List<Ljava/util/concurrent/locks/Lock;>;\";\n        final String lockLinkedList = \"Ljava/util/LinkedList<Ljava/util/concurrent/locks/Lock;>;\";\n\n        String actualType = determineMostSpecificType(lockList, lockLinkedList);\n        assertEquals(lockLinkedList, actualType);\n\n        actualType = determineMostSpecificType(lockLinkedList, lockList);\n        assertEquals(lockLinkedList, actualType);\n    }\n\n    @Test\n    public void testDetermineMostSpecificTypeParameterizedInnerInheritance() {\n        final String lockList = \"Ljava/util/List<Ljava/util/concurrent/locks/Lock;>;\";\n        final String stampedLockLinkedList = \"Ljava/util/LinkedList<Ljava/util/concurrent/locks/ReentrantLock;>;\";\n\n        String actualType = determineMostSpecificType(lockList, stampedLockLinkedList);\n        assertEquals(stampedLockLinkedList, actualType);\n\n        actualType = determineMostSpecificType(stampedLockLinkedList, lockList);\n        assertEquals(stampedLockLinkedList, actualType);\n    }\n\n    @Test\n    public void testToReadableTypes() {\n        assertEquals(\"com.sebastian_daschner.model.Model\", toReadableType(\"Lcom/sebastian_daschner/model/Model;\"));\n        assertEquals(\"com.sebastian_daschner.model.Enumeration\", toReadableType(\"Lcom/sebastian_daschner/model/Enumeration;\"));\n        assertEquals(\"java.util.List<com.sebastian_daschner.model.Enumeration>\", toReadableType(\"Ljava/util/List<Lcom/sebastian_daschner/model/Enumeration;>;\"));\n        assertEquals(\"java.util.List<com.sebastian_daschner.model.Model>\", toReadableType(\"Ljava/util/List<Lcom/sebastian_daschner/model/Model;>;\"));\n        assertEquals(\"java.util.List<? extends com.sebastian_daschner.model.Model>\", toReadableType(\"Ljava/util/List<+Lcom/sebastian_daschner/model/Model;>;\"));\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/analysis/utils/TestClassUtils.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.analysis.utils;\n\nimport java.io.File;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class TestClassUtils {\n\n    private TestClassUtils() {\n        // no instances allowed\n    }\n\n    /**\n     * Returns all root class names of compilation units in the given package.\n     *\n     * @param packageName The package name where to search\n     * @return All found classes except inner classes\n     * @throws ClassNotFoundException If a class could not be found\n     */\n    public static Set<String> getClasses(final String packageName) throws ClassNotFoundException {\n        final Set<String> classes = new HashSet<>();\n\n        final String postfixPackageName = packageName + '/';\n\n        final String classPath = new File(TestClassUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getAbsolutePath();\n        final Path testClassesDir = Paths.get(classPath + (classPath.endsWith(File.separator) ? \"\" : File.separatorChar) + postfixPackageName.replace('/', File.separatorChar));\n\n        final File[] testClasses = testClassesDir.toFile().listFiles((dir, name) -> name.endsWith(\"class\") && !name.contains(\"$\"));\n\n        for (final File classFile : testClasses) {\n            // load test class\n            final String classFileName = classFile.getName();\n            classes.add(postfixPackageName + classFileName.substring(0, classFileName.length() - \".class\".length()));\n        }\n\n        return classes;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/JsonRepresentationAppenderTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentationVisitor;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\npublic class JsonRepresentationAppenderTest {\n\n    private static final TypeIdentifier STRING_LIST_IDENTIFIER = TypeIdentifier.ofType(\"java.util.List<java.lang.String>\");\n    private static final TypeIdentifier STRING_IDENTIFIER = TypeIdentifier.ofType(Types.STRING);\n    private static final TypeIdentifier INT_IDENTIFIER = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n\n    private TypeRepresentationVisitor cut;\n    private Map<TypeIdentifier, TypeRepresentation> representations;\n    private StringBuilder builder;\n\n    @Before\n    public void setup() {\n        representations = new HashMap<>();\n        builder = new StringBuilder();\n        cut = new JsonRepresentationAppender(builder, representations);\n    }\n\n    @Test\n    public void testVisitPrimitive() {\n        TypeRepresentation.ofConcrete(TypeIdentifier.ofType(Types.STRING)).accept(cut);\n        assertThat(builder.toString(), is(\"\\\"string\\\"\"));\n    }\n\n    @Test\n    public void testMissingRepresentation() {\n        TypeRepresentation.ofCollection(STRING_LIST_IDENTIFIER, TypeRepresentation.ofConcrete(STRING_IDENTIFIER)).accept(cut);\n        assertThat(builder.toString(), is(\"[\\\"string\\\"]\"));\n    }\n\n    @Test\n    public void testEnum() {\n        TypeRepresentation.ofEnum(STRING_IDENTIFIER, \"Foo\", \"bar\").accept(cut);\n        assertThat(builder.toString(), is(\"\\\"Foo|bar\\\"\"));\n    }\n\n    @Test\n    public void testEnumEmpty() {\n        TypeRepresentation.ofEnum(STRING_IDENTIFIER).accept(cut);\n        assertThat(builder.toString(), is(\"\\\"string\\\"\"));\n    }\n\n    @Test\n    public void testVisitSimpleList() {\n        final TypeRepresentation stringRepresentation = TypeRepresentation.ofConcrete(STRING_IDENTIFIER);\n        final TypeRepresentation listRepresentation = TypeRepresentation.ofCollection(STRING_LIST_IDENTIFIER, stringRepresentation);\n        representations.put(STRING_LIST_IDENTIFIER, listRepresentation);\n\n        listRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"[\\\"string\\\"]\"));\n\n        clear(builder);\n        listRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"[\\\"string\\\"]\"));\n\n        clear(builder);\n        listRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"[\\\"string\\\"]\"));\n\n        clear(builder);\n        stringRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"\\\"string\\\"\"));\n    }\n\n    @Test\n    public void testVisitMultipleList() {\n        final TypeIdentifier identifier = TypeIdentifier.ofType(\"java.util.List<java.util.List<java.lang.String>>\");\n        final TypeRepresentation representation = TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofCollection(STRING_LIST_IDENTIFIER,\n                TypeRepresentation.ofConcrete(STRING_IDENTIFIER)));\n        representations.put(identifier, representation);\n\n        representation.accept(cut);\n        assertThat(builder.toString(), is(\"[[\\\"string\\\"]]\"));\n\n        clear(builder);\n        representation.accept(cut);\n        assertThat(builder.toString(), is(\"[[\\\"string\\\"]]\"));\n\n        clear(builder);\n        representation.accept(cut);\n        assertThat(builder.toString(), is(\"[[\\\"string\\\"]]\"));\n    }\n\n    @Test\n    public void testVisitDynamic() {\n        TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic()).accept(cut);\n        assertThat(builder.toString(), is(\"{}\"));\n\n        clear(builder);\n        TypeRepresentation.ofCollection(TypeIdentifier.ofDynamic(), TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic())).accept(cut);\n        assertThat(builder.toString(), is(\"[{}]\"));\n    }\n\n    @Test\n    public void testVisitConcrete() {\n        final TypeIdentifier identifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.Model\");\n        final TypeIdentifier enumIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.TestEnum\");\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"enumeration\", enumIdentifier);\n        final TypeRepresentation representation = TypeRepresentation.ofConcrete(identifier, properties);\n        final TypeRepresentation enumRepresentation = TypeRepresentation.ofEnum(identifier, \"FOO\", \"BAR\", \"BAZ\");\n\n        representations.put(identifier, representation);\n        representations.put(enumIdentifier, enumRepresentation);\n        representation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"enumeration\\\":\\\"BAR|BAZ|FOO\\\",\\\"hello\\\":\\\"string\\\",\\\"world\\\":0}\"));\n    }\n\n    @Test\n    public void testVisitConcreteWithNested() {\n        final TypeIdentifier identifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.Model\");\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"model\", identifier);\n        final TypeRepresentation representation = TypeRepresentation.ofConcrete(identifier, properties);\n\n        representations.put(identifier, representation);\n        representation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0}\"));\n    }\n\n    @Test\n    public void testVisitConcreteWithNestedPreventSuppression() {\n        final TypeIdentifier dateIdentifier = TypeIdentifier.ofType(Types.DATE);\n        final TypeIdentifier modelIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.Model\");\n        final TypeIdentifier objectIdentifier = TypeIdentifier.ofType(Types.OBJECT);\n\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"model\", modelIdentifier);\n        final TypeRepresentation dateRepresentation = TypeRepresentation.ofConcrete(dateIdentifier, properties);\n        representations.put(dateIdentifier, dateRepresentation);\n\n        properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"model\", modelIdentifier);\n        final TypeRepresentation objectRepresentation = TypeRepresentation.ofConcrete(objectIdentifier, properties);\n        representations.put(objectIdentifier, objectRepresentation);\n\n        properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"date\", dateIdentifier);\n        properties.put(\"object\", objectIdentifier);\n        final TypeRepresentation modelRepresentation = TypeRepresentation.ofConcrete(modelIdentifier, properties);\n        representations.put(modelIdentifier, modelRepresentation);\n\n        // date\n        // {\\\"abc\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0}\n        // object\n        // {\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0}\n        // model\n        // {\\\"abc\\\":\\\"string\\\",\\\"date\\\":{},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{},\\\"world\\\":0}\n\n        dateRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"world\\\":0},\\\"world\\\":0}\"));\n\n        clear(builder);\n        objectRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{},\\\"world\\\":0},\\\"world\\\":0}\"));\n\n        clear(builder);\n        modelRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"world\\\":0}\"));\n\n        clear(builder);\n        dateRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"world\\\":0},\\\"world\\\":0}\"));\n\n        clear(builder);\n        objectRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{},\\\"world\\\":0},\\\"world\\\":0}\"));\n\n        clear(builder);\n        modelRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\\\"abc\\\":\\\"string\\\",\\\"date\\\":{\\\"abc\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"hello\\\":\\\"string\\\",\\\"object\\\":{\\\"abc\\\":\\\"string\\\",\\\"hello\\\":\\\"string\\\",\\\"model\\\":{},\\\"world\\\":0},\\\"world\\\":0}\"));\n    }\n\n    @Test\n    public void testVisitRecursiveType() {\n        final TypeIdentifier modelIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.Model\");\n\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"abc\", STRING_IDENTIFIER);\n        properties.put(\"model\", modelIdentifier);\n        final TypeRepresentation modelRepresentation = TypeRepresentation.ofConcrete(modelIdentifier, properties);\n        representations.put(modelIdentifier, modelRepresentation);\n\n        modelRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\" +\n                \"\\\"abc\\\":\\\"string\\\",\" +\n                \"\\\"hello\\\":\\\"string\\\",\" +\n                \"\\\"model\\\":{},\" +\n                \"\\\"world\\\":0\" +\n                \"}\"));\n    }\n\n    @Test\n    public void testVisitCyclicRecursiveType() {\n        final TypeIdentifier firstModelIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.first.Model\");\n        final TypeIdentifier secondModelIdentifier = TypeIdentifier.ofType(\"com.sebastian_daschner.test.second.Model\");\n\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"world\", INT_IDENTIFIER);\n        properties.put(\"model\", secondModelIdentifier);\n        final TypeRepresentation firstModelRepresentation = TypeRepresentation.ofConcrete(firstModelIdentifier, properties);\n        representations.put(firstModelIdentifier, firstModelRepresentation);\n\n        properties = new HashMap<>();\n        properties.put(\"hello\", STRING_IDENTIFIER);\n        properties.put(\"model\", firstModelIdentifier);\n        final TypeRepresentation secondModelRepresentation = TypeRepresentation.ofConcrete(secondModelIdentifier, properties);\n        representations.put(secondModelIdentifier, secondModelRepresentation);\n\n        firstModelRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\" +\n                \"\\\"model\\\":{\\\"hello\\\":\\\"string\\\",\\\"model\\\":{}},\" +\n                \"\\\"world\\\":0\" +\n                \"}\"));\n\n        clear(builder);\n        secondModelRepresentation.accept(cut);\n        assertThat(builder.toString(), is(\"{\" +\n                \"\\\"hello\\\":\\\"string\\\",\" +\n                \"\\\"model\\\":{\\\"model\\\":{},\\\"world\\\":0}\" +\n                \"}\"));\n    }\n\n    private static void clear(final StringBuilder builder) {\n        builder.delete(0, builder.length());\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/asciidoc/AsciiDocBackendTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.asciidoc;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourceMethodBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourcesBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.ENUM_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.MODEL_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend.INLINE_PRETTIFY;\nimport static java.util.Collections.singletonMap;\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(Parameterized.class)\npublic class AsciiDocBackendTest {\n\n    private final Backend cut;\n    private final Resources resources;\n    private final String expectedOutput;\n    private final boolean inlinePrettify;\n\n    public AsciiDocBackendTest(Resources resources, String expectedOutput, boolean inlinePrettify) {\n        cut = new AsciiDocBackend();\n        this.resources = resources;\n        this.expectedOutput = expectedOutput;\n        this.inlinePrettify = inlinePrettify;\n    }\n\n    @Test\n    public void test() {\n        final Project project = new Project(\"project name\", \"1.0\", resources);\n        cut.configure(singletonMap(INLINE_PRETTIFY, String.valueOf(inlinePrettify)));\n        final String actualOutput = new String(cut.render(project));\n\n        assertEquals(expectedOutput, actualOutput);\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        final Collection<Object[]> data = new LinkedList<>();\n        final TypeIdentifier stringIdentifier = TypeIdentifier.ofType(Types.STRING);\n        final TypeIdentifier intIdentifier = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n\n        TypeIdentifier identifier;\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final Resources getRestRes1String = ResourcesBuilder.withBase(\"rest\")\n                .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Lorem Ipsum\")\n                        .andResponse(200,\n                                ResponseBuilder.withResponseBody(\n                                        TypeIdentifier.ofType(\n                                                Types.STRING))\n                                        .andHeaders(\n                                                \"Location\")\n                                        .build())\n                        .build())\n                .build();\n        add(data, getRestRes1String,\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Description: Lorem Ipsum\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", false);\n\n        add(data, getRestRes1String,\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Description: Lorem Ipsum\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", true);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        final Resources getRestRes1Json = ResourcesBuilder.withBase(\"rest\")\n                .andTypeRepresentation(identifier,\n                        TypeRepresentation.ofConcrete(identifier, properties))\n                .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                        .andResponse(200,\n                                ResponseBuilder.withResponseBody(\n                                        identifier)\n                                        .build())\n                        .build())\n                .build();\n        add(data, getRestRes1Json,\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n[source,javascript]\\n\" + \"----\\n\" + \"{\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}\\n\" + \"----\\n\\n\\n\\n\", false);\n        add(data, getRestRes1Json,\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n[source,javascript]\\n\" + \"----\\n\" + \"{\\n\" + \"    \\\"another\\\": 0,\\n\" + \"    \\\"key\\\": \\\"string\\\"\\n\" + \"}\\n\" + \"----\\n\\n\\n\\n\", true);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n[source,javascript]\\n\" + \"----\\n\" + \"[{\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}]\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofDynamic();\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(stringIdentifier)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Response Body*: (`javax.json.Json`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"[\\\"string\\\"]\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Response Body*: (`javax.json.Json`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"[{\\\"key\\\":\\\"string\\\"}]\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(MODEL_IDENTIFIER).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Response Body*: (`com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofType(\"Ljava/util/List<Lcom/sebastian_daschner/test/Model;>;\");\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Response Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofType(\"Ljava/util/List<Lcom/sebastian_daschner/test/Enumeration;>;\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofEnum(ENUM_IDENTIFIER, \"VALUE\", \"ANOTHER_VALUE\", \"OTHER\")))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Response Body*: (Collection of `com.sebastian_daschner.test.Enumeration`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"[\\\"ANOTHER_VALUE|OTHER|VALUE\\\"]\\n\" + \"----\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofType(\"Ljava/util/List<Lcom/sebastian_daschner/test/Model;>;\");\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andFormParam(\"form\", MODEL_IDENTIFIER.getType())\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `POST rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"*Content-Type*: `application/json` + \\n\" +\n                        \"*Request Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"[source,javascript]\\n\" + \"----\\n\" + \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" + \"----\\n\\n\\n\" +\n                        \"*Form Param*: `form`, `com.sebastian_daschner.test.Model` + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `201 Created`\\n\" +\n                        \"*Header*: `Location` + \\n\\n\", false);\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andQueryParam(\"query\", Types.PRIMITIVE_INT)\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build())\n                        .andResource(\"res2\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponse(200, ResponseBuilder.newBuilder().build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `POST rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"*Content-Type*: `application/json` + \\n\" +\n                        \"*Request Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"[source,javascript]\\n\" +\n                        \"----\\n\" +\n                        \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" +\n                        \"----\\n\\n\\n\" +\n                        \"*Query Param*: `query`, `int` + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `201 Created`\\n\" +\n                        \"*Header*: `Location` + \\n\\n\" +\n                        \"== `GET rest/res2`\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\\n\", false);\n        // deprecated method test\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res19\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andDeprecated(true)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"= REST resources of project name\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"== `GET rest/res19`\\n\" +\n                        \"\\n\" +\n                        \"CAUTION: deprecated\\n\" +\n                        \"\\n\" +\n                        \"=== Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"=== Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"==== `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", false);\n        return data;\n    }\n\n    public static void add(final Collection<Object[]> data, final Resources resources, final String output,\n                           final boolean pretty) {\n        final Object[] objects = new Object[3];\n        objects[0] = resources;\n        objects[1] = output;\n        objects[2] = pretty;\n        data.add(objects);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/markdown/MarkdownBackendTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.markdown;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourceMethodBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourcesBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Project;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport static java.util.Collections.singletonMap;\n\nimport static org.junit.Assert.assertEquals;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.MODEL_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend.INLINE_PRETTIFY;\n\n\n@RunWith(Parameterized.class)\npublic class MarkdownBackendTest {\n\n    private final Backend cut;\n    private final Resources resources;\n    private final String expectedOutput;\n    private final boolean inlinePrettify;\n\n    public MarkdownBackendTest(Resources resources, String expectedOutput, boolean inlinePrettify) {\n        cut = new MarkdownBackend();\n        this.resources = resources;\n        this.expectedOutput = expectedOutput;\n        this.inlinePrettify = inlinePrettify;\n    }\n\n    @Test\n    public void test() {\n        final Project project = new Project(\"project name\", \"1.0\", resources);\n        cut.configure(singletonMap(INLINE_PRETTIFY, String.valueOf(inlinePrettify)));\n        final String actualOutput = new String(cut.render(project));\n\n        assertEquals(expectedOutput, actualOutput);\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        final Collection<Object[]> data = new LinkedList<>();\n        final TypeIdentifier stringIdentifier = TypeIdentifier.ofType(Types.STRING);\n        final TypeIdentifier intIdentifier = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n\n        TypeIdentifier identifier;\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        final Resources getRestRes1String = ResourcesBuilder.withBase(\"rest\")\n                .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Lorem Ipsum\")\n                        .andResponse(200,\n                                ResponseBuilder.withResponseBody(\n                                        TypeIdentifier.ofType(\n                                                Types.STRING))\n                                        .andHeaders(\n                                                \"Location\")\n                                        .build())\n                        .build())\n                .build();\n        add(data, getRestRes1String,\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Description: Lorem Ipsum\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", false);\n\n        add(data, getRestRes1String,\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Description: Lorem Ipsum\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", true);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        final Resources getRestRes1Json = ResourcesBuilder.withBase(\"rest\")\n                .andTypeRepresentation(identifier,\n                        TypeRepresentation.ofConcrete(identifier, properties))\n                .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                        .andResponse(200,\n                                ResponseBuilder.withResponseBody(\n                                        identifier)\n                                        .build())\n                        .build())\n                .build();\n        add(data, getRestRes1Json,\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n```javascript\\n\" + \"{\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}\\n\" + \"```\\n\\n\\n\\n\", false);\n        add(data, getRestRes1Json,\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n```javascript\\n\" + \"{\\n\" + \"    \\\"another\\\": 0,\\n\" + \"    \\\"key\\\": \\\"string\\\"\\n\" + \"}\\n\" + \"```\\n\\n\\n\\n\", true);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" + \"*Response Body*: (`javax.json.Json`)\\n\\n```javascript\\n\" + \"[{\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}]\\n\" + \"```\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofDynamic();\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(stringIdentifier)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Response Body*: (`javax.json.Json`)\\n\\n\" +\n                        \"```javascript\\n\" + \"[\\\"string\\\"]\\n\" + \"```\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Response Body*: (`javax.json.Json`)\\n\\n\" +\n                        \"```javascript\\n\" + \"[{\\\"key\\\":\\\"string\\\"}]\\n\" + \"```\\n\\n\\n\\n\", false);\n\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(MODEL_IDENTIFIER).build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Response Body*: (`com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"```javascript\\n\" + \"{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}\\n\" + \"```\\n\\n\\n\\n\", false);\n\n        identifier = TypeIdentifier.ofType(\"Ljava/util/List<Lcom/sebastian_daschner/test/Model;>;\");\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Response Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"```javascript\\n\" + \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" + \"```\\n\\n\\n\\n\", false);\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andFormParam(\"form\", MODEL_IDENTIFIER.getType())\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `POST rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"*Content-Type*: `application/json` + \\n\" +\n                        \"*Request Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"```javascript\\n\" + \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" + \"```\\n\\n\\n\" +\n                        \"*Form Param*: `form`, `com.sebastian_daschner.test.Model` + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `201 Created`\\n\" +\n                        \"*Header*: `Location` + \\n\\n\", false);\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andQueryParam(\"query\", Types.PRIMITIVE_INT)\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build())\n                        .andResource(\"res2\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponse(200, ResponseBuilder.newBuilder().build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `POST rest/res1`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"*Content-Type*: `application/json` + \\n\" +\n                        \"*Request Body*: (Collection of `com.sebastian_daschner.test.Model`)\\n\\n\" +\n                        \"```javascript\\n\" +\n                        \"[{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" +\n                        \"```\\n\\n\\n\" +\n                        \"*Query Param*: `query`, `int` + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `201 Created`\\n\" +\n                        \"*Header*: `Location` + \\n\\n\" +\n                        \"## `GET rest/res2`\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\\n\", false);\n        // deprecated method test\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res19\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andDeprecated(true)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"# REST resources of project name\\n\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"## `GET rest/res19`\\n\" +\n                        \"\\n\" +\n                        \"CAUTION: deprecated\\n\" +\n                        \"\\n\" +\n                        \"### Request\\n\" +\n                        \"_No body_ + \\n\" +\n                        \"\\n\" +\n                        \"### Response\\n\" +\n                        \"*Content-Type*: `\\\\*/*`\\n\" +\n                        \"\\n\" +\n                        \"#### `200 OK`\\n\" +\n                        \"*Header*: `Location` + \\n\" +\n                        \"*Response Body*: (`java.lang.String`)\\n\\n\", false);\n        return data;\n    }\n\n    public static void add(final Collection<Object[]> data, final Resources resources, final String output,\n                           final boolean pretty) {\n        final Object[] objects = new Object[3];\n        objects[0] = resources;\n        objects[1] = output;\n        objects[2] = pretty;\n        data.add(objects);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/plaintext/PlainTextBackendTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.plaintext;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourceMethodBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourcesBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Project;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport static java.util.Collections.singletonMap;\n\nimport static org.junit.Assert.assertEquals;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.MODEL_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend.INLINE_PRETTIFY;\n\n@RunWith(Parameterized.class)\npublic class PlainTextBackendTest {\n\n    private final Backend cut;\n    private final Resources resources;\n    private final String expectedOutput;\n\n    public PlainTextBackendTest(final Resources resources, final String expectedOutput) {\n        cut = new PlainTextBackend();\n        this.resources = resources;\n        this.expectedOutput = expectedOutput;\n    }\n\n    @Test\n    public void test() {\n        final Project project = new Project(\"project name\", \"1.0\", resources);\n        cut.configure(singletonMap(INLINE_PRETTIFY, \"false\"));\n        final String actualOutput = new String(cut.render(project));\n        assertEquals(expectedOutput, actualOutput);\n    }\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        final Collection<Object[]> data = new LinkedList<>();\n        final TypeIdentifier stringIdentifier = TypeIdentifier.ofType(Types.STRING);\n        final TypeIdentifier intIdentifier = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n\n        TypeIdentifier identifier;\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        add(data, ResourcesBuilder.withBase(\"rest\").andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET, \"Lorem Ipsum\")\n                        .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res1:\\n\" +\n                        \"Description: Lorem Ipsum\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Header: Location\\n\" +\n                        \"   Response Body: java.lang.String\\n\\n\\n\");\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofConcrete(identifier, properties))\n                        .andResource(\"res2\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res2:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: javax.json.Json\\n\" +\n                        \"    {\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}\\n\\n\\n\");\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res3\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res3:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: javax.json.Json\\n\" +\n                        \"    [{\\\"another\\\":0,\\\"key\\\":\\\"string\\\"}]\\n\\n\\n\");\n\n        identifier = TypeIdentifier.ofDynamic();\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(stringIdentifier)))\n                        .andResource(\"res4\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res4:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: javax.json.Json\\n\" +\n                        \"    [\\\"string\\\"]\\n\\n\\n\");\n\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res5\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res5:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: javax.json.Json\\n\" +\n                        \"    [{\\\"key\\\":\\\"string\\\"}]\\n\\n\\n\");\n\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties))\n                        .andResource(\"res6\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(MODEL_IDENTIFIER).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res6:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: com.sebastian_daschner.test.Model\\n\" +\n                        \"    {\\\"name\\\":\\\"string\\\",\\\"value\\\":0}\\n\\n\\n\");\n\n        identifier = TypeIdentifier.ofType(\"Ljava/util/List<Lcom/sebastian_daschner/test/Model;>;\");\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res7\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res7:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\" +\n                        \"   Response Body: Collection of com.sebastian_daschner.test.Model\\n\" +\n                        \"    [{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\\n\\n\");\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res8\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andFormParam(\"form\", MODEL_IDENTIFIER.getType())\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"POST rest/res8:\\n\" +\n                        \" Request:\\n\" +\n                        \"  Content-Type: application/json\\n\" +\n                        \"  Request Body: Collection of com.sebastian_daschner.test.Model\\n\" +\n                        \"   [{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" +\n                        \"  Form Param: form, com.sebastian_daschner.test.Model\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 201\\n\" +\n                        \"   Header: Location\\n\\n\\n\");\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res9\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(identifier).andQueryParam(\"query\", Types.PRIMITIVE_INT)\n                                .andAcceptMediaTypes(\"application/json\").andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build())\n                        .andResource(\"res10\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andResponse(200, ResponseBuilder.newBuilder().build()).build()).build(),\n                \"REST resources of project name:\\n\" +\n                        \"1.0\\n\" +\n                        \"\\n\" +\n                        \"GET rest/res10:\\n\" +\n                        \" Request:\\n\" +\n                        \"  No body\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 200\\n\\n\\n\" +\n                        \"POST rest/res9:\\n\" +\n                        \" Request:\\n\" +\n                        \"  Content-Type: application/json\\n\" +\n                        \"  Request Body: Collection of com.sebastian_daschner.test.Model\\n\" +\n                        \"   [{\\\"name\\\":\\\"string\\\",\\\"value\\\":0}]\\n\" +\n                        \"  Query Param: query, int\\n\" +\n                        \"\\n\" +\n                        \" Response:\\n\" +\n                        \"  Content-Type: */*\\n\" +\n                        \"  Status Codes: 201\\n\" +\n                        \"   Header: Location\\n\\n\\n\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n            .andResource(\"res19\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andDeprecated(true)\n                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n            \"REST resources of project name:\\n\" +\n                    \"1.0\\n\" +\n                    \"\\n\" +\n                    \"GET rest/res19:\\n\" +\n                    \" Deprecated\\n\" +\n                    \" Request:\\n\" +\n                    \"  No body\\n\" +\n                    \"\\n\" +\n                    \" Response:\\n\" +\n                    \"  Content-Type: */*\\n\" +\n                    \"  Status Codes: 200\\n\" +\n                    \"   Header: Location\\n\" +\n                    \"   Response Body: java.lang.String\\n\\n\\n\");\n        return data;\n    }\n\n    public static void add(final Collection<Object[]> data, final Resources resources, final String output) {\n        final Object[] objects = new Object[2];\n        objects[0] = resources;\n        objects[1] = output;\n        data.add(objects);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SchemaBuilderTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.swagger.TypeIdentifierTestSupport.resetTypeIdentifierCounter;\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\npublic class SchemaBuilderTest {\n\n    private static final TypeIdentifier INTEGER_IDENTIFIER = TypeIdentifier.ofType(Types.INTEGER);\n    private static final TypeIdentifier INT_LIST_IDENTIFIER = TypeIdentifier.ofType(\"Ljava/util/List<Ljava/lang/Integer;>;\");\n\n    private SchemaBuilder cut;\n    private final Map<TypeIdentifier, TypeRepresentation> representations = new HashMap<>();\n\n    @Before\n    public void resetRepresentations() {\n        representations.clear();\n        resetTypeIdentifierCounter();\n    }\n\n    @Test\n    public void testSimpleDefinitions() {\n        representations.put(INT_LIST_IDENTIFIER, TypeRepresentation.ofCollection(INTEGER_IDENTIFIER, TypeRepresentation.ofConcrete(INTEGER_IDENTIFIER)));\n\n        final TypeIdentifier modelIdentifier = MODEL_IDENTIFIER;\n        final Map<String, TypeIdentifier> modelProperties = new HashMap<>();\n\n        modelProperties.put(\"test1\", INT_IDENTIFIER);\n        modelProperties.put(\"hello1\", STRING_IDENTIFIER);\n        modelProperties.put(\"array1\", INT_LIST_IDENTIFIER);\n\n        representations.put(modelIdentifier, TypeRepresentation.ofConcrete(modelIdentifier, modelProperties));\n\n        final Map<String, TypeIdentifier> dynamicProperties = new HashMap<>();\n\n        dynamicProperties.put(\"test2\", INT_IDENTIFIER);\n        dynamicProperties.put(\"hello2\", STRING_IDENTIFIER);\n        dynamicProperties.put(\"array2\", INT_LIST_IDENTIFIER);\n\n        final TypeIdentifier nestedDynamicIdentifier = TypeIdentifier.ofDynamic();\n        final Map<String, TypeIdentifier> nestedDynamicProperties = new HashMap<>();\n        nestedDynamicProperties.put(\"test\", INT_IDENTIFIER);\n\n        dynamicProperties.put(\"object2\", nestedDynamicIdentifier);\n\n        representations.put(nestedDynamicIdentifier, TypeRepresentation.ofConcrete(nestedDynamicIdentifier, nestedDynamicProperties));\n        representations.put(OBJECT_IDENTIFIER, TypeRepresentation.ofConcrete(OBJECT_IDENTIFIER, dynamicProperties));\n\n        cut = new SchemaBuilder(representations);\n        assertThat(cut.build(modelIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Model\").build()));\n        assertThat(cut.build(OBJECT_IDENTIFIER).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Object\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"Model\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .add(\"JsonObject\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder().add(\"test\", type(\"integer\"))))\n                .add(\"Object\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array2\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello2\", type(\"string\"))\n                        .add(\"object2\", Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\"))\n                        .add(\"test2\", type(\"integer\"))))\n                .build()));\n    }\n\n    @Test\n    public void testMultipleDefinitionsNameCollisions() {\n        final TypeIdentifier lockIdentifier = TypeIdentifier.ofType(\"Ljava/util/concurrent/locks/Lock;\");\n        final TypeIdentifier anotherLockIdentifier = TypeIdentifier.ofType(\"Ljavax/ejb/Lock;\");\n\n        final Map<String, TypeIdentifier> lockProperties = new HashMap<>();\n        lockProperties.put(\"test1\", INT_IDENTIFIER);\n        lockProperties.put(\"hello1\", STRING_IDENTIFIER);\n        lockProperties.put(\"array1\", INT_LIST_IDENTIFIER);\n\n        final Map<String, TypeIdentifier> anotherLockProperties = new HashMap<>();\n        anotherLockProperties.put(\"test1\", INT_IDENTIFIER);\n        anotherLockProperties.put(\"hello1\", STRING_IDENTIFIER);\n        anotherLockProperties.put(\"array1\", INT_LIST_IDENTIFIER);\n\n        representations.put(INT_LIST_IDENTIFIER, TypeRepresentation.ofCollection(INTEGER_IDENTIFIER, TypeRepresentation.ofConcrete(INTEGER_IDENTIFIER)));\n        representations.put(lockIdentifier, TypeRepresentation.ofConcrete(lockIdentifier, lockProperties));\n        representations.put(anotherLockIdentifier, TypeRepresentation.ofConcrete(anotherLockIdentifier, anotherLockProperties));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(lockIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Lock\").build()));\n        assertThat(cut.build(anotherLockIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Lock_2\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"Lock\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .add(\"Lock_2\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .build()));\n    }\n\n    @Test\n    public void testSingleDynamicDefinitionMissingNestedType() {\n        final TypeIdentifier identifier = TypeIdentifier.ofDynamic();\n\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n        properties.put(\"test1\", INT_IDENTIFIER);\n        properties.put(\"hello1\", STRING_IDENTIFIER);\n        // unknown type identifier\n        properties.put(\"array1\", INT_LIST_IDENTIFIER);\n\n        representations.put(identifier, TypeRepresentation.ofConcrete(identifier, properties));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(identifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"JsonObject\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"object\"))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .build()));\n    }\n\n    @Test\n    public void testMultipleDifferentDefinitions() {\n        final Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        properties.put(\"test1\", INT_IDENTIFIER);\n        properties.put(\"hello1\", STRING_IDENTIFIER);\n        properties.put(\"array1\", INT_LIST_IDENTIFIER);\n\n        representations.put(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties));\n        representations.put(INT_LIST_IDENTIFIER, TypeRepresentation.ofCollection(INTEGER_IDENTIFIER, TypeRepresentation.ofConcrete(INTEGER_IDENTIFIER)));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(MODEL_IDENTIFIER).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Model\").build()));\n        assertThat(cut.build(TypeIdentifier.ofType(Types.OBJECT)).build(), is(Json.createObjectBuilder().add(\"type\", \"object\").build()));\n        // build with different type identifier instance\n        assertThat(cut.build(TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/Model;\")).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Model\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"Model\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .build()));\n    }\n\n    @Test\n    public void testSameDynamicDefinitions() {\n        final TypeIdentifier firstIdentifier = TypeIdentifier.ofDynamic();\n        final TypeIdentifier secondIdentifier = TypeIdentifier.ofDynamic();\n\n        final Map<String, TypeIdentifier> firstProperties = new HashMap<>();\n        firstProperties.put(\"test1\", INT_IDENTIFIER);\n        firstProperties.put(\"hello1\", STRING_IDENTIFIER);\n        firstProperties.put(\"array1\", INT_LIST_IDENTIFIER);\n        firstProperties.put(\"nested\", secondIdentifier);\n\n        final Map<String, TypeIdentifier> secondProperties = new HashMap<>();\n        secondProperties.put(\"nested\", firstIdentifier);\n\n        representations.put(INT_LIST_IDENTIFIER, TypeRepresentation.ofCollection(INTEGER_IDENTIFIER, TypeRepresentation.ofConcrete(INTEGER_IDENTIFIER)));\n        representations.put(firstIdentifier, TypeRepresentation.ofConcrete(firstIdentifier, firstProperties));\n        representations.put(secondIdentifier, TypeRepresentation.ofConcrete(secondIdentifier, secondProperties));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(firstIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\").build()));\n        assertThat(cut.build(firstIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\").build()));\n        assertThat(cut.build(secondIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_2\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"JsonObject\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"array1\", Json.createObjectBuilder().add(\"type\", \"array\").add(\"items\", type(\"integer\")))\n                        .add(\"hello1\", type(\"string\"))\n                        .add(\"nested\", Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_2\"))\n                        .add(\"test1\", type(\"integer\"))))\n                .add(\"JsonObject_2\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"nested\", Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\"))))\n                .build()));\n    }\n\n    @Test\n    public void testDifferentDynamicDefinitions() {\n        final TypeIdentifier firstIdentifier = TypeIdentifier.ofDynamic();\n        final TypeIdentifier secondIdentifier = TypeIdentifier.ofDynamic();\n        final TypeIdentifier thirdIdentifier = TypeIdentifier.ofDynamic();\n\n        final Map<String, TypeIdentifier> firstProperties = new HashMap<>();\n        firstProperties.put(\"_links\", secondIdentifier);\n\n        final Map<String, TypeIdentifier> secondProperties = new HashMap<>();\n        secondProperties.put(\"self\", thirdIdentifier);\n\n        final Map<String, TypeIdentifier> thirdProperties = new HashMap<>();\n        thirdProperties.put(\"href\", STRING_IDENTIFIER);\n\n        representations.put(firstIdentifier, TypeRepresentation.ofConcrete(firstIdentifier, firstProperties));\n        representations.put(secondIdentifier, TypeRepresentation.ofConcrete(secondIdentifier, secondProperties));\n        representations.put(thirdIdentifier, TypeRepresentation.ofConcrete(thirdIdentifier, thirdProperties));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(firstIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject\").build()));\n        assertThat(cut.build(secondIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_2\").build()));\n        assertThat(cut.build(thirdIdentifier).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_3\").build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"JsonObject\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"_links\", Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_2\"))))\n                .add(\"JsonObject_2\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"self\", Json.createObjectBuilder().add(\"$ref\", \"#/definitions/JsonObject_3\"))))\n                .add(\"JsonObject_3\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"href\", type(\"string\"))))\n                .build()));\n    }\n\n    @Test\n    public void testEnumDefinitions() {\n        final TypeIdentifier enumIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/Enumeration;\");\n        final Map<String, TypeIdentifier> modelProperties = new HashMap<>();\n\n        modelProperties.put(\"foobar\", enumIdentifier);\n        modelProperties.put(\"hello1\", STRING_IDENTIFIER);\n\n        representations.put(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, modelProperties));\n        representations.put(enumIdentifier, TypeRepresentation.ofEnum(enumIdentifier, \"THIRD\", \"FIRST\", \"SECOND\"));\n\n        cut = new SchemaBuilder(representations);\n\n        assertThat(cut.build(MODEL_IDENTIFIER).build(), is(Json.createObjectBuilder().add(\"$ref\", \"#/definitions/Model\").build()));\n        assertThat(cut.build(enumIdentifier).build(), is(Json.createObjectBuilder().add(\"type\", \"string\")\n                .add(\"enum\", Json.createArrayBuilder().add(\"FIRST\").add(\"SECOND\").add(\"THIRD\")).build()));\n\n        final JsonObject definitions = cut.getDefinitions();\n        assertThat(definitions, is(Json.createObjectBuilder()\n                .add(\"Model\", Json.createObjectBuilder().add(\"properties\", Json.createObjectBuilder()\n                        .add(\"foobar\", Json.createObjectBuilder().add(\"type\", \"string\").add(\"enum\", Json.createArrayBuilder().add(\"FIRST\").add(\"SECOND\").add(\"THIRD\")))\n                        .add(\"hello1\", type(\"string\"))))\n                .build()));\n    }\n\n    private static JsonObject type(final String type) {\n        return Json.createObjectBuilder().add(\"type\", type).build();\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/SwaggerBackendTest.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.backend.Backend;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourceMethodBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResourcesBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.builder.ResponseBuilder;\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport javax.json.Json;\nimport javax.json.JsonStructure;\nimport java.io.StringReader;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.MODEL_IDENTIFIER;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend.INLINE_PRETTIFY;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.swagger.SwaggerOptions.*;\nimport static com.sebastian_daschner.jaxrs_analyzer.backend.swagger.TypeIdentifierTestSupport.*;\nimport static java.util.Collections.singletonMap;\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(Parameterized.class)\npublic class SwaggerBackendTest {\n\n    private final Backend cut;\n    private final Resources resources;\n    private final String expectedOutput;\n\n    public SwaggerBackendTest(final Resources resources, final String expectedOutput, final Map<String, String> options) {\n        cut = new SwaggerBackend();\n        cut.configure(options);\n        this.resources = resources;\n        this.expectedOutput = expectedOutput;\n    }\n\n    @Test\n    public void test() {\n        final Project project = new Project(\"project name\", \"1.0\", resources);\n        cut.configure(singletonMap(INLINE_PRETTIFY, \"false\"));\n        final String actualOutput = new String(cut.render(project));\n\n        // TODO to fix test w/ different formattings\n//            assertEquals(expectedOutput, actualOutput);\n\n        try (final StringReader expectedReader = new StringReader(expectedOutput);\n             final StringReader actualReader = new StringReader(actualOutput)\n        ) {\n            final JsonStructure expected = Json.createReader(expectedReader).read();\n            final JsonStructure actual = Json.createReader(actualReader).read();\n            assertEquals(expected, actual);\n        }\n    }\n\n\n    @Parameterized.Parameters\n    public static Collection<Object[]> data() {\n        final Collection<Object[]> data = new LinkedList<>();\n        final TypeIdentifier stringIdentifier = TypeIdentifier.ofType(Types.STRING);\n        final TypeIdentifier intIdentifier = TypeIdentifier.ofType(Types.PRIMITIVE_INT);\n\n        TypeIdentifier identifier;\n        Map<String, TypeIdentifier> properties = new HashMap<>();\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"\\\",\\\"basePath\\\":\\\"/project name/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res1\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}},\\\"definitions\\\":{}}\", new HashMap<>());\n\n        Map<String, String> options = new HashMap<>();\n        options.put(SWAGGER_SCHEMES, \"https,wss\");\n        options.put(DOMAIN, \"example.com\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res1\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"https\\\",\\\"wss\\\"],\\\"paths\\\":{\\\"/res1\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}},\\\"definitions\\\":{}}\",\n                options);\n\n        resetTypeIdentifierCounter();\n        identifier = TypeIdentifier.ofDynamic();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\").andTypeRepresentation(identifier, TypeRepresentation.ofConcrete(identifier, properties))\n                        .andResource(\"res2\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res2\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/JsonObject\\\"}}}}}},\\\"definitions\\\":{\\\"JsonObject\\\":{\\\"properties\\\":{\\\"another\\\":{\\\"type\\\":\\\"integer\\\"},\\\"key\\\":{\\\"type\\\":\\\"string\\\"}}}}}\");\n\n        resetTypeIdentifierCounter();\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        properties.put(\"another\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), properties)))\n                        .andResource(\"res3\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res3\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/definitions/JsonObject_2\\\"}}}}}}},\\\"definitions\\\":{\\\"JsonObject_2\\\":{\\\"properties\\\":{\\\"another\\\":{\\\"type\\\":\\\"integer\\\"},\\\"key\\\":{\\\"type\\\":\\\"string\\\"}}}}}\");\n\n        resetTypeIdentifierCounter();\n        identifier = TypeIdentifier.ofDynamic();\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(stringIdentifier)))\n                        .andResource(\"res4\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res4\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"type\\\":\\\"string\\\"}}}}}}},\\\"definitions\\\":{}}\");\n\n        resetTypeIdentifierCounter();\n        identifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"key\", stringIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(identifier, properties)))\n                        .andResource(\"res5\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res5\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/definitions/JsonObject\\\"}}}}}}},\\\"definitions\\\":{\\\"JsonObject\\\":{\\\"properties\\\":{\\\"key\\\":{\\\"type\\\":\\\"string\\\"}}}}}\");\n\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties))\n                        .andResource(\"res6\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(MODEL_IDENTIFIER).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res6\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/Model\\\"}}}}}},\\\"definitions\\\":{\\\"Model\\\":{\\\"properties\\\":{\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"value\\\":{\\\"type\\\":\\\"integer\\\"}}}}}\");\n\n        identifier = TypeIdentifier.ofType(\"Ljavax/ws/rs/core/StreamingOutput;\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(identifier, TypeRepresentation.ofConcrete(identifier))\n                        .andResource(\"res7\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(identifier).build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res7\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{},\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/StreamingOutput\\\"}}}}}},\\\"definitions\\\":{\\\"StreamingOutput\\\":{\\\"properties\\\":{}}}}\");\n\n        final TypeIdentifier dynamicIdentifier = TypeIdentifier.ofDynamic();\n        properties = new HashMap<>();\n        properties.put(\"name\", stringIdentifier);\n        properties.put(\"value\", intIdentifier);\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(dynamicIdentifier, TypeRepresentation.ofCollection(MODEL_IDENTIFIER, TypeRepresentation.ofConcrete(MODEL_IDENTIFIER, properties)))\n                        .andResource(\"res8\", ResourceMethodBuilder.withMethod(HttpMethod.POST).andRequestBodyType(dynamicIdentifier).andAcceptMediaTypes(\"application/json\")\n                                .andResponse(201, ResponseBuilder.newBuilder().andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res8\\\":{\\\"post\\\":{\\\"consumes\\\":[\\\"application/json\\\"],\\\"produces\\\":[],\\\"parameters\\\":[{\\\"name\\\":\\\"body\\\",\\\"in\\\":\\\"body\\\",\\\"required\\\":true,\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/definitions/Model\\\"}}}],\\\"responses\\\":{\\\"201\\\":{\\\"description\\\":\\\"Created\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}}}}}}},\\\"definitions\\\":{\\\"Model\\\":{\\\"properties\\\":{\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"value\\\":{\\\"type\\\":\\\"integer\\\"}}}}}\");\n\n        options = new HashMap<>();\n        options.put(DOMAIN, \"domain.tld\");\n        options.put(SWAGGER_SCHEMES, \"http,https\");\n        options.put(RENDER_SWAGGER_TAGS, \"true\");\n        options.put(SWAGGER_TAGS_PATH_OFFSET, \"0\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res09\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build())\n                        .andResource(\"res10\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"domain.tld\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\",\\\"https\\\"],\\\"tags\\\":[{\\\"name\\\":\\\"res09\\\"},{\\\"name\\\":\\\"res10\\\"}],\\\"paths\\\":{\"\n                        + \"\\\"/res09\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"tags\\\":[\\\"res09\\\"]}},\"\n                        + \"\\\"/res10\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"tags\\\":[\\\"res10\\\"]}}\"\n                        + \"},\\\"definitions\\\":{}}\",\n                options);\n\n        options = new HashMap<>();\n        options.put(RENDER_SWAGGER_TAGS, \"true\");\n        options.put(DOMAIN, \"example.com\");\n        options.put(SWAGGER_TAGS_PATH_OFFSET, \"1\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"v2/res11\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build())\n                        .andResource(\"v2/res12\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"tags\\\":[{\\\"name\\\":\\\"res11\\\"},{\\\"name\\\":\\\"res12\\\"}],\\\"paths\\\":{\"\n                        + \"\\\"/v2/res11\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"tags\\\":[\\\"res11\\\"]}},\"\n                        + \"\\\"/v2/res12\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"tags\\\":[\\\"res12\\\"]}}\"\n                        + \"},\\\"definitions\\\":{}}\",\n                options);\n\n        options = new HashMap<>();\n        options.put(DOMAIN, \"domain.tld\");\n        options.put(SWAGGER_SCHEMES, \"http,https\");\n        options.put(RENDER_SWAGGER_TAGS, \"true\");\n        options.put(SWAGGER_TAGS_PATH_OFFSET, \"42\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"v2/res13\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build())\n                        .andResource(\"v2/res14\", ResourceMethodBuilder.withMethod(HttpMethod.GET)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"domain.tld\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\",\\\"https\\\"],\\\"tags\\\":[],\\\"paths\\\":{\"\n                        + \"\\\"/v2/res13\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}},\"\n                        + \"\\\"/v2/res14\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}\"\n                        + \"},\\\"definitions\\\":{}}\",\n                options);\n\n        // query parameter tests\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(dynamicIdentifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(identifier, properties)))\n                        .andResource(\"res15\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andQueryParam(\"value\", \"Ljava/lang/Integer;\").andAcceptMediaTypes(\"application/json\")\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res15\\\":{\\\"get\\\":{\\\"consumes\\\":[\\\"application/json\\\"],\\\"produces\\\":[],\\\"parameters\\\":[{\\\"type\\\":\\\"integer\\\",\\\"name\\\":\\\"value\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":true}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}},\\\"definitions\\\":{}}\");\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(dynamicIdentifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(identifier, properties)))\n                        .andResource(\"res16\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andQueryParam(\"value\", \"Ljava/lang/Integer;\", \"test\").andAcceptMediaTypes(\"application/json\")\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res16\\\":{\\\"get\\\":{\\\"consumes\\\":[\\\"application/json\\\"],\\\"produces\\\":[],\\\"parameters\\\":[{\\\"type\\\":\\\"integer\\\",\\\"name\\\":\\\"value\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":false,\\\"default\\\":\\\"test\\\"}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}},\\\"definitions\\\":{}}\");\n\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andTypeRepresentation(dynamicIdentifier, TypeRepresentation.ofCollection(identifier, TypeRepresentation.ofConcrete(identifier, properties)))\n                        .andResource(\"res17\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andQueryParam(\"value\", \"Ljava/lang/Integer;\").andQueryParam(\"name\", \"Ljava/lang/String;\", \"foobar\").andAcceptMediaTypes(\"application/json\")\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res17\\\":{\\\"get\\\":{\\\"consumes\\\":[\\\"application/json\\\"],\\\"produces\\\":[],\\\"parameters\\\":[{\\\"type\\\":\\\"string\\\",\\\"name\\\":\\\"name\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":false,\\\"default\\\":\\\"foobar\\\"},{\\\"type\\\":\\\"integer\\\",\\\"name\\\":\\\"value\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":true}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}}}}},\\\"definitions\\\":{}}\");\n\n        // Enum type tests\n        identifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/FirstEnum;\");\n        final TypeIdentifier secondIdentifier = TypeIdentifier.ofType(\"Lcom/sebastian_daschner/test/SecondEnum;\");\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res18\", ResourceMethodBuilder\n                                .withMethod(HttpMethod.GET)\n                                .andQueryParam(\"q1\", identifier.getType())\n                                .andQueryParam(\"q2\", secondIdentifier.getType())\n                                .build()\n                        ).andTypeRepresentation(identifier, TypeRepresentation.ofEnum(identifier, \"APPLE\", \"BANANA\"))\n                        .andTypeRepresentation(secondIdentifier, TypeRepresentation.ofEnum(secondIdentifier, \"APPLE\", \"BANANA\"))\n                        .build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"example.com\\\",\\\"basePath\\\":\\\"/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res18\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"APPLE\\\",\\\"BANANA\\\"],\\\"name\\\":\\\"q1\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":true},{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"APPLE\\\",\\\"BANANA\\\"],\\\"name\\\":\\\"q2\\\",\\\"in\\\":\\\"query\\\",\\\"required\\\":true}],\\\"responses\\\":{}}}},\\\"definitions\\\":{}}\"\n        );\n\n        // deprecated method test\n        add(data, ResourcesBuilder.withBase(\"rest\")\n                        .andResource(\"res19\", ResourceMethodBuilder.withMethod(HttpMethod.GET).andDeprecated(true)\n                                .andResponse(200, ResponseBuilder.withResponseBody(TypeIdentifier.ofType(Types.STRING)).andHeaders(\"Location\").build()).build()).build(),\n                \"{\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0\\\",\\\"title\\\":\\\"project name\\\"},\\\"host\\\":\\\"\\\",\\\"basePath\\\":\\\"/project name/rest\\\",\\\"schemes\\\":[\\\"http\\\"],\\\"paths\\\":{\\\"/res19\\\":{\\\"get\\\":{\\\"consumes\\\":[],\\\"produces\\\":[],\\\"parameters\\\":[],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\",\\\"headers\\\":{\\\"Location\\\":{\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"deprecated\\\":true}}},\\\"definitions\\\":{}}\", new HashMap<>());\n\n        return data;\n    }\n\n    public static void add(final Collection<Object[]> data, final Resources resources, final String output) {\n        Map<String, String> options = new HashMap<>();\n        options.put(DOMAIN, \"example.com\");\n        add(data, resources, output, options);\n    }\n\n    public static void add(final Collection<Object[]> data, final Resources resources, final String output, final Map<String, String> options) {\n        final Object[] objects = new Object[3];\n        objects[0] = resources;\n        objects[1] = output;\n        objects[2] = options;\n        data.add(objects);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/backend/swagger/TypeIdentifierTestSupport.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.backend.swagger;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\n\nimport java.lang.reflect.Field;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nfinal class TypeIdentifierTestSupport {\n\n    private TypeIdentifierTestSupport() {\n    }\n\n    static void resetTypeIdentifierCounter() {\n        try {\n            Field dynamicCounterField = TypeIdentifier.class.getDeclaredField(\"dynamicCounter\");\n            dynamicCounterField.setAccessible(true);\n            AtomicInteger dynamicCounter = (AtomicInteger) dynamicCounterField.get(null);\n            dynamicCounter.set(0);\n        } catch (ReflectiveOperationException e) {\n            throw new IllegalStateException(\"Could not reset the counter via reflection.\", e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/ClassResultBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.ClassResult;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.Arrays;\nimport java.util.stream.Stream;\n\npublic class ClassResultBuilder {\n\n    private final ClassResult classResult = new ClassResult();\n\n    private ClassResultBuilder() {\n        // prevent other instances\n    }\n\n    public static ClassResultBuilder withApplicationPath(final String applicationPath) {\n        final ClassResultBuilder classResultBuilder = new ClassResultBuilder();\n        classResultBuilder.classResult.setApplicationPath(applicationPath);\n        return classResultBuilder;\n    }\n\n    public static ClassResultBuilder withResourcePath(final String resourcePath) {\n        final ClassResultBuilder classResultBuilder = new ClassResultBuilder();\n        classResultBuilder.classResult.setResourcePath(resourcePath);\n        return classResultBuilder;\n    }\n\n    public ClassResultBuilder andMethods(final MethodResult... methodResults) {\n        Stream.of(methodResults).forEach(classResult::add);\n        return this;\n    }\n\n    public ClassResultBuilder andAcceptMediaTypes(final String... mediaType) {\n        classResult.getRequestMediaTypes().addAll(Arrays.asList(mediaType));\n        return this;\n    }\n\n    public ClassResultBuilder andResponseMediaTypes(final String... mediaType) {\n        classResult.getResponseMediaTypes().addAll(Arrays.asList(mediaType));\n        return this;\n    }\n\n    public ClassResultBuilder andMatrixParam(final String name, final String type) {\n        andParam(ParameterType.MATRIX, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andMatrixParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.MATRIX, name, type, defaultValue);\n        return this;\n    }\n\n    public ClassResultBuilder andQueryParam(final String name, final String type) {\n        andParam(ParameterType.QUERY, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andQueryParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.QUERY, name, type, defaultValue);\n        return this;\n    }\n\n    public ClassResultBuilder andPathParam(final String name, final String type) {\n        andParam(ParameterType.PATH, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andPathParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.PATH, name, type, defaultValue);\n        return this;\n    }\n\n    public ClassResultBuilder andCookieParam(final String name, final String type) {\n        andParam(ParameterType.COOKIE, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andCookieParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.COOKIE, name, type, defaultValue);\n        return this;\n    }\n\n    public ClassResultBuilder andHeaderParam(final String name, final String type) {\n        andParam(ParameterType.HEADER, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andHeaderParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.HEADER, name, type, defaultValue);\n        return this;\n    }\n\n    public ClassResultBuilder andFormParam(final String name, final String type) {\n        andParam(ParameterType.FORM, name, type, null);\n        return this;\n    }\n\n    public ClassResultBuilder andFormParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.FORM, name, type, defaultValue);\n        return this;\n    }\n\n    private ClassResultBuilder andParam(final ParameterType parameterType, final String name, final String type, final String defaultValue) {\n        final MethodParameter methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);\n        methodParameter.setName(name);\n        methodParameter.setDefaultValue(defaultValue);\n        classResult.getClassFields().add(methodParameter);\n        return this;\n    }\n\n    public ClassResultBuilder andDeprecated(final boolean deprecated) {\n        classResult.setDeprecated(deprecated);\n        return this;\n    }\n\n    public ClassResult build() {\n        return classResult;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/HttpResponseBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue;\n\nimport java.util.stream.Stream;\n\npublic class HttpResponseBuilder {\n\n    private final HttpResponse httpResponse = new HttpResponse();\n\n    private HttpResponseBuilder() {\n        // prevent other instances\n    }\n\n    public static HttpResponseBuilder newBuilder() {\n        return new HttpResponseBuilder();\n    }\n\n    public static HttpResponseBuilder withStatues(final Integer... statues) {\n        final HttpResponseBuilder builder = new HttpResponseBuilder();\n        Stream.of(statues).forEach(builder.httpResponse.getStatuses()::add);\n        return builder;\n    }\n\n    public HttpResponseBuilder andInlineEntities(final JsonValue... jsonValues) {\n        Stream.of(jsonValues).forEach(httpResponse.getInlineEntities()::add);\n        return this;\n    }\n\n    public HttpResponseBuilder andHeaders(final String... headers) {\n        Stream.of(headers).forEach(httpResponse.getHeaders()::add);\n        return this;\n    }\n\n    public HttpResponseBuilder andContentTypes(final String... contentTypes) {\n        Stream.of(contentTypes).forEach(httpResponse.getContentTypes()::add);\n        return this;\n    }\n\n    public HttpResponseBuilder andEntityTypes(final String... entityTypes) {\n        Stream.of(entityTypes).forEach(httpResponse.getEntityTypes()::add);\n        return this;\n    }\n\n    public HttpResponse build() {\n        return httpResponse;\n    }\n\n}\n\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/MethodResultBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;\nimport com.sebastian_daschner.jaxrs_analyzer.model.javadoc.MethodComment;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.HttpMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.MethodParameter;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ParameterType;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;\n\nimport java.util.Arrays;\nimport java.util.stream.Stream;\n\npublic class MethodResultBuilder {\n\n    private final MethodResult methodResult = new MethodResult();\n\n    private MethodResultBuilder() {\n        // prevent other instances\n    }\n\n    public static MethodResultBuilder newBuilder() {\n        return new MethodResultBuilder();\n    }\n\n    public static MethodResultBuilder withResponses(final HttpResponse... responses) {\n        final MethodResultBuilder builder = new MethodResultBuilder();\n        Stream.of(responses).forEach(builder.methodResult.getResponses()::add);\n        return builder;\n    }\n\n    public MethodResultBuilder andMethodDoc(final MethodComment methodDoc) {\n        methodResult.setMethodDoc(methodDoc);\n        return this;\n    }\n\n    public MethodResultBuilder andPath(final String path) {\n        methodResult.setPath(path);\n        return this;\n    }\n\n    public MethodResultBuilder andMethod(final HttpMethod httpMethod) {\n        methodResult.setHttpMethod(httpMethod);\n        return this;\n    }\n\n    public MethodResultBuilder andRequestMediaTypes(final String... mediaTypes) {\n        methodResult.getRequestMediaTypes().addAll(Arrays.asList(mediaTypes));\n        return this;\n    }\n\n    public MethodResultBuilder andResponseMediaTypes(final String... mediaTypes) {\n        methodResult.getResponseMediaTypes().addAll(Arrays.asList(mediaTypes));\n        return this;\n    }\n\n    public MethodResultBuilder andRequestBodyType(final String type) {\n        methodResult.setRequestBodyType(type);\n        return this;\n    }\n\n    public MethodResultBuilder andMatrixParam(final String name, final String type) {\n        andParam(ParameterType.MATRIX, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andMatrixParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.MATRIX, name, type, defaultValue);\n        return this;\n    }\n\n    public MethodResultBuilder andQueryParam(final String name, final String type) {\n        andParam(ParameterType.QUERY, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andQueryParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.QUERY, name, type, defaultValue);\n        return this;\n    }\n\n    public MethodResultBuilder andPathParam(final String name, final String type) {\n        andParam(ParameterType.PATH, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andPathParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.PATH, name, type, defaultValue);\n        return this;\n    }\n\n    public MethodResultBuilder andCookieParam(final String name, final String type) {\n        andParam(ParameterType.COOKIE, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andCookieParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.COOKIE, name, type, defaultValue);\n        return this;\n    }\n\n    public MethodResultBuilder andHeaderParam(final String name, final String type) {\n        andParam(ParameterType.HEADER, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andHeaderParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.HEADER, name, type, defaultValue);\n        return this;\n    }\n\n    public MethodResultBuilder andFormParam(final String name, final String type) {\n        andParam(ParameterType.FORM, name, type, null);\n        return this;\n    }\n\n    public MethodResultBuilder andFormParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.FORM, name, type, defaultValue);\n        return this;\n    }\n\n    private MethodResultBuilder andParam(final ParameterType parameterType, final String name, final String type, final String defaultValue) {\n        final MethodParameter methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);\n        methodParameter.setName(name);\n        methodParameter.setDefaultValue(defaultValue);\n        methodResult.getMethodParameters().add(methodParameter);\n        return this;\n    }\n\n    public MethodResultBuilder andDeprecated(final boolean deprecated) {\n        methodResult.setDeprecated(deprecated);\n        return this;\n    }\n\n    public MethodResult build() {\n        return methodResult;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/ResourceMethodBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.*;\n\nimport java.util.Arrays;\n\npublic class ResourceMethodBuilder {\n\n    private final ResourceMethod method;\n\n    private ResourceMethodBuilder(final HttpMethod method) {\n        this.method = new ResourceMethod(method, null);\n    }\n\n    public ResourceMethodBuilder(final HttpMethod method, final String description) {\n        this.method = new ResourceMethod(method, description);\n    }\n\n    public static ResourceMethodBuilder withMethod(final HttpMethod method) {\n        return new ResourceMethodBuilder(method);\n    }\n\n    public static ResourceMethodBuilder withMethod(final HttpMethod method, final String description) {\n        return new ResourceMethodBuilder(method, description);\n    }\n\n    public ResourceMethodBuilder andRequestBodyType(final String type) {\n        method.setRequestBody(TypeIdentifier.ofType(type));\n        return this;\n    }\n\n    public ResourceMethodBuilder andRequestBodyType(final String type, final String requestBodyDescription) {\n        method.setRequestBody(TypeIdentifier.ofType(type));\n        method.setRequestBodyDescription(requestBodyDescription);\n        return this;\n    }\n\n    public ResourceMethodBuilder andRequestBodyType(final TypeIdentifier identifier) {\n        method.setRequestBody(identifier);\n        return this;\n    }\n\n    public ResourceMethodBuilder andResponse(final int status, final Response response) {\n        method.getResponses().put(status, response);\n        return this;\n    }\n\n    public ResourceMethodBuilder andAcceptMediaTypes(final String... mediaTypes) {\n        method.getRequestMediaTypes().addAll(Arrays.asList(mediaTypes));\n        return this;\n    }\n\n    public ResourceMethodBuilder andResponseMediaTypes(final String... mediaTypes) {\n        method.getResponseMediaTypes().addAll(Arrays.asList(mediaTypes));\n        return this;\n    }\n\n    public ResourceMethodBuilder andMatrixParam(final String name, final String type) {\n        andParam(ParameterType.MATRIX, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andMatrixParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.MATRIX, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andQueryParam(final String name, final String type) {\n        andParam(ParameterType.QUERY, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andQueryParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.QUERY, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andQueryParam(final String name, final String type, final String defaultValue, final String description) {\n        andParam(ParameterType.QUERY, name, type, defaultValue, description);\n        return this;\n    }\n\n    public ResourceMethodBuilder andPathParam(final String name, final String type) {\n        andParam(ParameterType.PATH, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andPathParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.PATH, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andPathParam(final String name, final String type, final String defaultValue, final String description) {\n        andParam(ParameterType.PATH, name, type, defaultValue, description);\n        return this;\n    }\n\n    public ResourceMethodBuilder andCookieParam(final String name, final String type) {\n        andParam(ParameterType.COOKIE, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andCookieParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.COOKIE, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andHeaderParam(final String name, final String type) {\n        andParam(ParameterType.HEADER, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andHeaderParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.HEADER, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andFormParam(final String name, final String type) {\n        andParam(ParameterType.FORM, name, type, null, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andFormParam(final String name, final String type, final String defaultValue) {\n        andParam(ParameterType.FORM, name, type, defaultValue, null);\n        return this;\n    }\n\n    public ResourceMethodBuilder andParam(final ParameterType parameterType, final String name, final String type, final String defaultValue, final String description) {\n        final MethodParameter methodParameter = new MethodParameter(TypeIdentifier.ofType(type), parameterType);\n        methodParameter.setName(name);\n        methodParameter.setDefaultValue(defaultValue);\n        methodParameter.setDescription(description);\n        method.getMethodParameters().add(methodParameter);\n        return this;\n    }\n\n    public ResourceMethodBuilder andDeprecated(final boolean deprecated) {\n        method.setDeprecated(deprecated);\n        return this;\n    }\n\n    public ResourceMethod build() {\n        return method;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/ResourcesBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.ResourceMethod;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Resources;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeRepresentation;\n\nimport java.util.stream.Stream;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ResourcesBuilder {\n\n    private final Resources resources;\n\n    private ResourcesBuilder() {\n        resources = new Resources();\n    }\n\n    public static ResourcesBuilder withBase(final String baseUri) {\n        final ResourcesBuilder builder = new ResourcesBuilder();\n        builder.resources.setBasePath(baseUri);\n        return builder;\n    }\n\n    public ResourcesBuilder andResource(final String resource, final ResourceMethod... method) {\n        Stream.of(method).forEach(m -> resources.addMethod(resource, m));\n        return this;\n    }\n\n    public ResourcesBuilder andTypeRepresentation(final TypeIdentifier identifier, final TypeRepresentation representation) {\n        resources.getTypeRepresentations().put(identifier, representation);\n        return this;\n    }\n\n    public Resources build() {\n        return resources;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/builder/ResponseBuilder.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_analyzer.builder;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.Response;\nimport com.sebastian_daschner.jaxrs_analyzer.model.rest.TypeIdentifier;\n\nimport java.util.stream.Stream;\n\n/**\n * @author Sebastian Daschner\n */\npublic class ResponseBuilder {\n\n    private final Response response;\n\n    private ResponseBuilder(final Response response) {\n        this.response = response;\n    }\n\n    public static ResponseBuilder newBuilder() {\n        return new ResponseBuilder(new Response());\n    }\n\n    public static ResponseBuilder withResponseBody(final TypeIdentifier responseBody) {\n        return new ResponseBuilder(new Response(responseBody));\n    }\n\n    public ResponseBuilder andHeaders(final String... headers) {\n        Stream.of(headers).forEach(response.getHeaders()::add);\n        return this;\n    }\n\n    public Response build() {\n        return response;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/model/rest/CollectionTypeRepresentationTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.rest;\n\nimport com.sebastian_daschner.jaxrs_analyzer.model.Types;\nimport org.junit.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.sebastian_daschner.jaxrs_analyzer.analysis.results.TypeUtils.*;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class CollectionTypeRepresentationTest {\n\n    @Test\n    public void testContentEqualsConcrete() {\n        final TypeRepresentation.ConcreteTypeRepresentation stringRepresentation = (TypeRepresentation.ConcreteTypeRepresentation) TypeRepresentation.ofConcrete(TypeIdentifier.ofType(Types.STRING));\n        final TypeRepresentation.ConcreteTypeRepresentation objectRepresentation = (TypeRepresentation.ConcreteTypeRepresentation) TypeRepresentation.ofConcrete(TypeIdentifier.ofType(Types.OBJECT));\n\n        assertTrue(stringRepresentation.contentEquals(objectRepresentation.getProperties()));\n\n        final Map<String, TypeIdentifier> firstProperties = new HashMap<>();\n        firstProperties.put(\"hello\", STRING_IDENTIFIER);\n        firstProperties.put(\"world\", INT_IDENTIFIER);\n        final TypeRepresentation.ConcreteTypeRepresentation firstRepresentation = (TypeRepresentation.ConcreteTypeRepresentation) TypeRepresentation.ofConcrete(OBJECT_IDENTIFIER, firstProperties);\n\n        final Map<String, TypeIdentifier> secondProperties = new HashMap<>();\n        secondProperties.put(\"hello\", STRING_IDENTIFIER);\n        secondProperties.put(\"world\", INT_IDENTIFIER);\n\n        assertTrue(firstRepresentation.contentEquals(secondProperties));\n    }\n\n    @Test\n    public void testContentEqualsCollection() {\n        final Map<String, TypeIdentifier> firstProperties = new HashMap<>();\n        firstProperties.put(\"hello\", STRING_IDENTIFIER);\n        firstProperties.put(\"world\", INT_IDENTIFIER);\n\n        final TypeRepresentation firstRepresentation = TypeRepresentation.ofConcrete(OBJECT_IDENTIFIER, firstProperties);\n        final TypeRepresentation secondRepresentation = TypeRepresentation.ofConcrete(OBJECT_IDENTIFIER, Collections.emptyMap());\n        final TypeRepresentation thirdRepresentation = TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), new HashMap<>(firstProperties));\n        final TypeRepresentation fourthRepresentation = TypeRepresentation.ofConcrete(TypeIdentifier.ofDynamic(), new HashMap<>(firstProperties));\n\n        final TypeRepresentation.CollectionTypeRepresentation firstCollection = (TypeRepresentation.CollectionTypeRepresentation) TypeRepresentation.ofCollection(TypeIdentifier.ofDynamic(), firstRepresentation);\n        final TypeRepresentation.CollectionTypeRepresentation secondCollection = (TypeRepresentation.CollectionTypeRepresentation) TypeRepresentation.ofCollection(TypeIdentifier.ofDynamic(), secondRepresentation);\n        final TypeRepresentation.CollectionTypeRepresentation thirdCollection = (TypeRepresentation.CollectionTypeRepresentation) TypeRepresentation.ofCollection(TypeIdentifier.ofDynamic(), thirdRepresentation);\n        final TypeRepresentation.CollectionTypeRepresentation fourthCollection = (TypeRepresentation.CollectionTypeRepresentation) TypeRepresentation.ofCollection(TypeIdentifier.ofDynamic(), fourthRepresentation);\n\n        assertTrue(firstCollection.contentEquals(secondCollection.getRepresentation()));\n        assertFalse(firstCollection.contentEquals(thirdCollection.getRepresentation()));\n        assertTrue(thirdCollection.contentEquals(fourthCollection.getRepresentation()));\n    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/jaxrs_analyzer/model/types/TypeTest.java",
    "content": "package com.sebastian_daschner.jaxrs_analyzer.model.types;\n\n/**\n * @author Sebastian Daschner\n */\npublic class TypeTest {\n\n    // TODO\n//    @Test\n//    public void testSimple() {\n//        final Type type = new Type(\"java.lang.String\");\n//        assertThat(type.getCtClass().getName(), is(\"java.lang.String\"));\n//        assertThat(type.toString(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//    }\n//\n//    @Test\n//    public void testSimpleMap() {\n//        final Type type = new Type(\"java.util.Map\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Map\"));\n//        assertThat(type.toString(), is(\"java.util.Map\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//        assertTrue(type.isAssignableTo(Types.MAP));\n//    }\n//\n//    @Test\n//    public void testParameterizedMap() {\n//        final Type type = new Type(\"java.util.Map<java.lang.String,java.lang.String>\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Map\"));\n//        assertThat(type.toString(), is(\"java.util.Map<java.lang.String, java.lang.String>\"));\n//        assertThat(type.getTypeParameters().size(), is(2));\n//        assertThat(type.getTypeParameters().get(0).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(0).toString(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(1).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(1).toString(), is(\"java.lang.String\"));\n//        assertTrue(type.isAssignableTo(Types.MAP));\n//    }\n//\n//    @Test\n//    public void testNestedSimpleClass() {\n//        final Type type = new Type(\"java.util.Map$Entry\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Map$Entry\"));\n//        assertThat(type.toString(), is(\"java.util.Map$Entry\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//        assertTrue(!type.isAssignableTo(Types.MAP));\n//    }\n//\n//    @Test\n//    public void testNestedParameterizedClass() {\n//        final Type type = new Type(\"java.util.Map$Entry<java.lang.String,java.lang.String>\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Map$Entry\"));\n//        assertThat(type.toString(), is(\"java.util.Map$Entry<java.lang.String, java.lang.String>\"));\n//        assertThat(type.getTypeParameters().size(), is(2));\n//        assertThat(type.getTypeParameters().get(0).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(0).toString(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(1).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertThat(type.getTypeParameters().get(1).toString(), is(\"java.lang.String\"));\n//        assertTrue(!type.isAssignableTo(Types.MAP));\n//    }\n//\n//    @Test\n//    public void testPrimitiveTypes() {\n//        final Type type = new Type(\"int\");\n//        assertThat(type.getCtClass().getName(), is(\"int\"));\n//        assertThat(type.toString(), is(\"int\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//        assertTrue(type.equals(Types.PRIMITIVE_INT));\n//    }\n//\n//    @Test\n//    public void testSimpleArrays() {\n//        final Type type = new Type(\"java.lang.String[]\");\n//        assertThat(type.getCtClass().getName(), is(\"java.lang.String[]\"));\n//        assertThat(type.toString(), is(\"java.lang.String[]\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//        assertTrue(!type.equals(Types.STRING));\n//    }\n//\n//    @Test\n//    public void testMultiDimensionalArrays() {\n//        final Type type = new Type(\"java.lang.String[][]\");\n//        assertThat(type.getCtClass().getName(), is(\"java.lang.String[][]\"));\n//        assertThat(type.toString(), is(\"java.lang.String[][]\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//        assertTrue(!type.equals(Types.STRING));\n//    }\n//\n//    @Test\n//    public void testParameterizedTypesInArrays() {\n//        final Type type = new Type(\"java.util.Collection<java.lang.String>[]\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Collection[]\"));\n//        assertThat(type.toString(), is(\"java.util.Collection<java.lang.String>[]\"));\n//        assertThat(type.getTypeParameters().size(), is(1));\n//        assertThat(type.getTypeParameters().get(0).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertTrue(!type.equals(Types.STRING));\n//    }\n//\n//    @Test\n//    public void testParameterizedTypesInList() {\n//        final Type type = new Type(\"java.util.List<java.lang.Long>\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.List\"));\n//        assertThat(type.toString(), is(\"java.util.List<java.lang.Long>\"));\n//        assertThat(type.getTypeParameters().size(), is(1));\n//        assertThat(type.getTypeParameters().get(0).getCtClass().getName(), is(\"java.lang.Long\"));\n//        assertTrue(!type.equals(Types.STRING));\n//    }\n//\n//    @Test\n//    public void testParameterizedTypesInMultiDimensionalArrays() {\n//        final Type type = new Type(\"java.util.Collection<java.lang.String>[][]\");\n//        assertThat(type.getCtClass().getName(), is(\"java.util.Collection[][]\"));\n//        assertThat(type.toString(), is(\"java.util.Collection<java.lang.String>[][]\"));\n//        assertThat(type.getTypeParameters().size(), is(1));\n//        assertThat(type.getTypeParameters().get(0).getCtClass().getName(), is(\"java.lang.String\"));\n//        assertTrue(!type.equals(Types.STRING));\n//    }\n//\n//    @Test\n//    public void testPrivateInterface() {\n//        final Type type = new Type(\"com.sebastian_daschner.jaxrs_analyzer.model.Types.TypeTest$ConfigurationManager$Configuration\");\n//        assertThat(type.getCtClass().getName(), is(\"com.sebastian_daschner.jaxrs_analyzer.model.Types.TypeTest$ConfigurationManager$Configuration\"));\n//        assertThat(type.toString(), is(\"com.sebastian_daschner.jaxrs_analyzer.model.Types.TypeTest$ConfigurationManager$Configuration\"));\n//        assertThat(type.getTypeParameters().size(), is(0));\n//    }\n//\n//    private interface ConfigurationManager {\n//        Configuration getConfiguration(String name);\n//\n//        class Configuration {\n//        }\n//    }\n\n}"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/test/Enumeration.java",
    "content": "package com.sebastian_daschner.test;\n\npublic enum Enumeration {\n    FIRST, SECOND, THIRD\n}\n"
  },
  {
    "path": "src/test/java/com/sebastian_daschner/test/Model.java",
    "content": "package com.sebastian_daschner.test;\n\npublic class Model {\n\n    // needed for tests\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/AbstractResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ws.rs.*;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\npublic abstract class AbstractResources {\n\n    @GET\n    @Path(\"{info}\")\n    public Response getInfo(@PathParam(\"info\") final String info) {\n        return Response.status(Response.Status.NOT_IMPLEMENTED).header(\"X-Info\", info + \" is not implemented\").build();\n    }\n\n    @GET\n    @Path(\"string\")\n    @Produces(MediaType.APPLICATION_JSON)\n    public Object getString() {\n        return new Object();\n    }\n\n    @PUT\n    public Response putComplex() {\n        return Response.status(Response.Status.NO_CONTENT).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/ComplexResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\nimport javax.inject.Inject;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.container.ResourceContext;\nimport javax.ws.rs.core.Context;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport javax.ws.rs.HeaderParam;\nimport java.util.ArrayList;\nimport static javax.ws.rs.core.HttpHeaders.AUTHORIZATION;\n\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Stateless\n@Path(\"complex\")\npublic class ComplexResources extends AbstractResources implements Resources {\n\n    @Context\n    ResourceContext rc;\n\n    @Inject\n    Manager<Integer> manager;\n\n    @Override\n    public Response getInfo(final String info) {\n        return Response.ok().header(\"X-Info\", manager.getInstance(String.class, info.length()) + \" is complex\").build();\n    }\n\n    @Override\n    public String getStatus() {\n        return \"status\";\n    }\n\n    @GET\n    @Produces(MediaType.APPLICATION_JSON)\n    public ArrayList<String> getStrings() {\n        final ArrayList<String> strings = new ArrayList<>();\n        strings.add(\"hi\");\n        strings.add(\"hello\");\n        return strings;\n    }\n\n    @Override\n    public String getString() {\n        return \"hello\";\n    }\n\n    @Path(\"sub\")\n    public SomeSubResource subResources() {\n        return createSomeSubResource();\n    }\n\n    private SomeSubResource createSomeSubResource() {\n        return new SubResources(\"complex\");\n    }\n\n    @Path(\"anotherSub\")\n    public SomeSubResource anotherSubResource() {\n        return rc.initResource(new SubResources(\"complex\"));\n    }\n\n    @Path(\"anotherSubres\")\n    public SomeSubResource anotherSubresResource() {\n        // just for testing, this would fail due to missing default constructor\n        return rc.getResource(SubResources.class);\n    }\n\n    /**\n     * Creates an authorization endpoint.\n     *\n     * @param token auth token\n     */\n    @GET\n    @Path(\"auth\")\n    public Response get(@HeaderParam(AUTHORIZATION) String token) {\n        return Response.ok(\"Authorized\").build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/Enumeration.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\npublic enum Enumeration {\n\n    VALUE, ANOTHER_VALUE, OTHER\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/IgnoredTestResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\nimport javax.inject.Inject;\nimport javax.persistence.EntityNotFoundException;\nimport javax.ws.rs.*;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.net.URI;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Logger;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Path(\"/ignored\")\n@Stateless\n@Consumes(MediaType.APPLICATION_JSON)\n@Produces(MediaType.APPLICATION_JSON)\npublic class IgnoredTestResources {\n\n    @Inject\n    private TestStore testStore;\n\n    /**\n     * Returns a test string with plain text.\n     *\n     * @return Ignore this comment\n     */\n    @GET\n    @Path(\"test\")\n    @Produces(MediaType.TEXT_HTML)\n    public Response test() {\n        return Response.ok(\"hello\", MediaType.TEXT_PLAIN_TYPE).build();\n    }\n\n    @GET\n    public List<? extends Model> getModels() {\n        return this.testStore.getModels();\n    }\n\n    public <T extends Comparable<? super T>> T foobar() {\n        return null;\n    }\n\n    @POST\n    public Response simplePost(String string) {\n        final Model managedModel = this.testStore.getModel(string);\n\n        final URI uri = URI.create(\"/ignored/\" + managedModel.getId());\n\n        return Response.created(uri).build();\n    }\n\n    @PUT\n    public Response put(final Model model) {\n        this.testStore.addModel(model);\n\n        return Response.accepted().build();\n    }\n\n    /**\n     * Deletes a test.\n     *\n     * @param foobar The foo query\n     */\n    @DELETE\n    @Path(\"{foobar}\")\n    public void deleteTest(@PathParam(\"foobar\") final String foobar) {\n        Logger.getLogger(\"\").info(\"deleted \" + foobar);\n    }\n\n    @GET\n    @Path(\"{id}\")\n    public Model getModel(@PathParam(\"id\") final String id) {\n        synchronized (this) {\n            return this.testStore.getModel(id);\n        }\n    }\n\n    @DELETE\n    @Path(\"{id}\")\n    public Response delete(@PathParam(\"id\") final Map<String, List<String>> id) {\n        try {\n            this.testStore.delete(\"id\");\n            return Response.noContent().build();\n        } catch (EntityNotFoundException e) {\n            return Response.status(Response.Status.NOT_FOUND).header(\"X-Message\", \"The entity with identifier \" + id + \" was not found.\").build();\n        } catch (Exception e) {\n            return Response.serverError().build();\n        }\n    }\n\n    /**\n     * Deletes another test.\n     *\n     * @param id    The ID\n     * @param query The deletion query\n     * @return\n     */\n    @DELETE\n    @Path(\"{id}/test\")\n    public Response anotherDelete(@PathParam(\"id\") final String id, @QueryParam(\"query\") final int query) {\n        try {\n            this.testStore.delete(id);\n            return Response.noContent().build();\n        } finally {\n            Logger.getLogger(\"\").info(\"deleted\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/JsonResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.json.Json;\nimport javax.json.JsonObject;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Path(\"json_tests\")\npublic class JsonResources {\n\n    @GET\n    public JsonObject getJson() {\n        return Json.createObjectBuilder().add(\"key\", \"value\").add(\"duke\", 42).build();\n    }\n\n    @POST\n    public Response post() {\n        if (\"\".equals(\"\"))\n            return Response.accepted(Json.createObjectBuilder().add(\"key\", \"value\").build()).build();\n        if (\"a\".equals(\"b\"))\n            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);\n        return Response.ok(Json.createArrayBuilder().add(\"duke\").add(42).build()).build();\n    }\n\n    @Path(\"info\")\n    @GET\n    public Response getInfo() {\n        return Response.ok(Json.createObjectBuilder().add(\"key\", \"value\").add(\"duke\", \"42\").add(\"hello\", \"world\")).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/Manager.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Stateless\npublic class Manager<T> {\n\n    public <U> U getInstance(final Class<U> clazz, final T object) {\n        // some reflection magic\n        final T tObject = object;\n        final U uObject = (U) object;\n        return uObject;\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/Model.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.persistence.*;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Entity\n@Table(name = \"models\")\n@NamedQuery(name = Model.FIND_ALL, query = \"select m from Model m\")\npublic class Model {\n\n    public static final String FIND_ALL = \"Model.findAll\";\n\n    @Id\n    @GeneratedValue\n    private long id;\n\n    @Basic(optional = false)\n    private String name;\n\n    public Model() {\n        // nothing to do\n    }\n\n    public Model(final String name) {\n        this.name = name;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(final long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(final String name) {\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return \"Model{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                '}';\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/ResourceWithoutClassLevelJavadoc.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\nimport javax.inject.Inject;\nimport javax.ws.rs.Consumes;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\n\n@Stateless\n@Path(\"resourceWithoutJavadoc\")\npublic class ResourceWithoutClassLevelJavadoc {\n\n    /**\n     * Simple field comment (see issue #178)\n     */\n    @Inject\n    Manager<Integer> manager;\n\n    /**\n     * Returns a test string in json.\n     *\n     * @return Ignore this comment\n     */\n    @GET\n    @Path(\"test\")\n    @Produces(MediaType.APPLICATION_JSON)\n    @Consumes(MediaType.APPLICATION_JSON)\n    public Response testJson() {\n        return Response.ok(\"{\\\"hi\\\":\\\"hello\\\"}\", MediaType.APPLICATION_JSON).build();\n    }\n\n}"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/Resources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\npublic interface Resources {\n\n    @GET\n    @Path(\"status\")\n    String getStatus();\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/RestActivator.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ws.rs.ApplicationPath;\nimport javax.ws.rs.core.Application;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@ApplicationPath(\"rest\")\npublic class RestActivator extends Application {\n    // no configuration needed\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/SomeSubResource.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\npublic interface SomeSubResource {\n    // just a marker interface\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/SubResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ws.rs.*;\nimport javax.ws.rs.core.Response;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Path(\"subsub\")\npublic class SubResources implements SomeSubResource {\n\n    private final String name;\n\n    /**\n     * The query param.\n     */\n    @QueryParam(\"query\")\n    private String query;\n\n    public SubResources(final String name) {\n        this.name = name;\n    }\n\n    /**\n     * Gets a sub resource.\n     *\n     * @param name The name\n     * @return\n     */\n    @GET\n    @Path(\"{name}\")\n    public String getSub(@PathParam(\"name\") final String name) {\n        return this.name + name;\n    }\n\n    /**\n     * Creates a sub resource.\n     *\n     * @param entity The entity\n     * @return\n     */\n    @POST\n    public Response postSub(final String entity) {\n        System.out.println(\"posted new: \" + entity + \" q: \" + query);\n        return Response.accepted().header(\"X-Info\", \"Added \" + entity).build();\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/Test.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE})\npublic @interface Test {\n\n    public static final String STATIC_STRING = \"123\";\n\n    String value() default \"value\";\n\n    int test();\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/TestResources.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\nimport javax.inject.Inject;\nimport javax.persistence.EntityNotFoundException;\nimport javax.ws.rs.*;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.Response;\nimport java.net.URI;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Logger;\nimport javax.validation.constraints.Pattern;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Path(\"/test\")\n@Stateless\n@Consumes(MediaType.APPLICATION_JSON)\n@Produces(MediaType.APPLICATION_JSON)\npublic class TestResources {\n\n    @Inject\n    private TestStore testStore;\n\n    /**\n     * Returns a test string with plain text.\n     *\n     * @return Ignore this comment\n     */\n    @GET\n    @Path(\"test\")\n    @Produces(MediaType.TEXT_HTML)\n    public Response test() {\n        return Response.ok(\"hi\", MediaType.TEXT_PLAIN_TYPE).build();\n    }\n\n    @GET\n    @Path(\"test\")\n    @Produces(MediaType.APPLICATION_JSON)\n    public Response testJson() {\n        return Response.ok(\"{\\\"hi\\\":\\\"hello\\\"}\", MediaType.APPLICATION_JSON).build();\n    }\n\n    @GET\n    public List<? extends Model> getModels() {\n        return this.testStore.getModels();\n    }\n\n    public <T extends Comparable<? super T>> T foobar() {\n        return null;\n    }\n\n    @POST\n    public Response simplePost(String string) {\n        final Model managedModel = this.testStore.getModel(string);\n\n        final URI uri = URI.create(\"/test/\" + managedModel.getId());\n\n        return Response.created(uri).build();\n    }\n\n    @PUT\n    public Response put(final Model model) {\n        this.testStore.addModel(model);\n\n        return Response.accepted().build();\n    }\n\n    /**\n     * Deletes a test.\n     *\n     * @param foobar The foo query\n     */\n    @DELETE\n    @Path(\"{foobar}\")\n    public void deleteTest(@PathParam(\"foobar\") @Pattern(regexp = \"^\\\\S.*\") final String foobar) {\n        Logger.getLogger(\"\").info(\"deleted \" + foobar);\n    }\n\n    @GET\n    @Path(\"{id}\")\n    public Model getModel(@PathParam(\"id\") final String id) {\n        synchronized (this) {\n            return this.testStore.getModel(id);\n        }\n    }\n\n    @DELETE\n    @Path(\"{id}\")\n    public Response delete(@PathParam(\"id\") final Map<String, List<String>> id) {\n        try {\n            this.testStore.delete(\"id\");\n            return Response.noContent().build();\n        } catch (EntityNotFoundException e) {\n            return Response.status(Response.Status.NOT_FOUND).header(\"X-Message\", \"The entity with identifier \" + id + \" was not found.\").build();\n        } catch (Exception e) {\n            return Response.serverError().build();\n        }\n    }\n\n    /**\n     * Deletes another test.\n     *\n     * @param id    The ID\n     * @param query The deletion query\n     * @return\n     */\n    @DELETE\n    @Path(\"{id}/test\")\n    public Response anotherDelete(@PathParam(\"id\") final String id, @QueryParam(\"query\") final int query) {\n        try {\n            this.testStore.delete(id);\n            return Response.noContent().build();\n        } finally {\n            Logger.getLogger(\"\").info(\"deleted\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/jaxrs-test/com/sebastian_daschner/jaxrs_test/TestStore.java",
    "content": "/*\n * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.sebastian_daschner.jaxrs_test;\n\nimport javax.ejb.Stateless;\nimport java.util.List;\n\n/**\n * These sources are solely used for test purposes and not meant for deployment.\n */\n@Stateless\npublic class TestStore {\n\n    public Model getModel(final String id) {\n        return null;\n    }\n\n    public String addModel(final Model model) {\n        return null;\n    }\n\n    public List<Model> getModels() {\n        return null;\n    }\n\n    public void delete(final String id) {\n        // do nothing\n    }\n\n}\n"
  }
]