Full Code of terran4j/commons for AI

master 863b68f3fb91 cached
446 files
2.1 MB
565.3k tokens
3080 symbols
1 requests
Download .txt
Showing preview only (2,347K chars total). Download the full file or copy to clipboard to get everything.
Repository: terran4j/commons
Branch: master
Commit: 863b68f3fb91
Files: 446
Total size: 2.1 MB

Directory structure:
gitextract_jq1qgnkm/

├── .gitignore
├── LICENSE
├── README.md
├── build.txt
├── commons-api2doc/
│   ├── .gitignore
│   ├── README.md
│   ├── doc/
│   │   ├── TODO.md
│   │   └── aboutCurl.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── api2doc/
│       │   │                   ├── Api2DocMocker.java
│       │   │                   ├── annotations/
│       │   │                   │   ├── Api2Doc.java
│       │   │                   │   ├── ApiComment.java
│       │   │                   │   ├── ApiError.java
│       │   │                   │   └── ApiErrors.java
│       │   │                   ├── codewriter/
│       │   │                   │   ├── CodeConfig.java
│       │   │                   │   ├── CodeOutput.java
│       │   │                   │   ├── CodeUtils.java
│       │   │                   │   ├── EnumCodeWriter.java
│       │   │                   │   ├── FileCodeOutput.java
│       │   │                   │   ├── JavaBeanCodeWriter.java
│       │   │                   │   ├── MemoryCodeOutput.java
│       │   │                   │   └── RetrofitCodeWriter.java
│       │   │                   ├── config/
│       │   │                   │   ├── Api2DocConfiguration.java
│       │   │                   │   └── EnableApi2Doc.java
│       │   │                   ├── controller/
│       │   │                   │   ├── Api2DocController.java
│       │   │                   │   ├── ApiEntry.java
│       │   │                   │   ├── ApiInfo.java
│       │   │                   │   ├── ApiMetaController.java
│       │   │                   │   └── MenuData.java
│       │   │                   ├── domain/
│       │   │                   │   ├── ApiDataType.java
│       │   │                   │   ├── ApiDocObject.java
│       │   │                   │   ├── ApiDocUtils.java
│       │   │                   │   ├── ApiErrorObject.java
│       │   │                   │   ├── ApiFolderObject.java
│       │   │                   │   ├── ApiObject.java
│       │   │                   │   ├── ApiParamLocation.java
│       │   │                   │   ├── ApiParamObject.java
│       │   │                   │   ├── ApiResultObject.java
│       │   │                   │   └── DateConverter.java
│       │   │                   ├── impl/
│       │   │                   │   ├── Api2DocCollector.java
│       │   │                   │   ├── Api2DocObjectFactory.java
│       │   │                   │   ├── Api2DocProperties.java
│       │   │                   │   ├── Api2DocService.java
│       │   │                   │   ├── Api2DocUtils.java
│       │   │                   │   ├── ApiCommentUtils.java
│       │   │                   │   ├── ClasspathFreeMarker.java
│       │   │                   │   ├── CurlBuilder.java
│       │   │                   │   ├── DocMenuBuilder.java
│       │   │                   │   ├── DocPageBuilder.java
│       │   │                   │   ├── FlexibleString.java
│       │   │                   │   └── MappingMethod.java
│       │   │                   └── meta/
│       │   │                       ├── ApiMetaService.java
│       │   │                       ├── ClassMeta.java
│       │   │                       ├── MethodMeta.java
│       │   │                       └── ParamMeta.java
│       │   └── resources/
│       │       ├── api2doc/
│       │       │   └── welcome.md
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── api2doc/
│       │       │               ├── codewriter/
│       │       │               │   ├── bean.java.ftl
│       │       │               │   ├── enum.java.ftl
│       │       │               │   └── retrofit.java.ftl
│       │       │               └── impl/
│       │       │                   └── doc.md.ftl
│       │       ├── static/
│       │       │   └── api2doc/
│       │       │       ├── css/
│       │       │       │   ├── doc.less
│       │       │       │   ├── home.less
│       │       │       │   ├── md.less
│       │       │       │   └── test.less
│       │       │       ├── flexible-lite/
│       │       │       │   └── flexible-lite-1.0.js
│       │       │       ├── less/
│       │       │       │   └── less-1.7.0.js
│       │       │       ├── test.html
│       │       │       └── vue/
│       │       │           └── vue-2.5.10.js
│       │       └── templates/
│       │           └── api2doc/
│       │               ├── doc.ftl
│       │               └── home.ftl
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           ├── demo/
│           │           │   └── api2doc/
│           │           │       ├── Api2DocDemoApp.java
│           │           │       ├── CodeGenerator.java
│           │           │       ├── FileInfo.java
│           │           │       ├── ShowMappingController.java
│           │           │       ├── ShowParamController.java
│           │           │       ├── ShowResultController.java
│           │           │       ├── User.java
│           │           │       ├── UserController.java
│           │           │       ├── UserController1.java
│           │           │       ├── UserController2.java
│           │           │       ├── UserController3.java
│           │           │       ├── UserGroup.java
│           │           │       └── UserType.java
│           │           └── test/
│           │               └── api2doc/
│           │                   ├── Api2DocCollectorTest.java
│           │                   ├── Api2DocObjectFactoryTest.java
│           │                   ├── Api2DocUtilsTest.java
│           │                   ├── ApiCommentUtilsTest.java
│           │                   ├── ApiResultObjectTest.java
│           │                   ├── Application.java
│           │                   ├── BaseApi2DocTest.java
│           │                   ├── CurlBuilderTest.java
│           │                   ├── JavaBeanCodeWriterTest.java
│           │                   ├── MyBean.java
│           │                   ├── ParseApiCommentOnMethod.java
│           │                   ├── ParseApiCommentOnParam.java
│           │                   ├── ParseApiCommentOnSeeClass.java
│           │                   ├── ParseApiCommentOnSeeClassLoop.java
│           │                   ├── ParseEnumTest.java
│           │                   ├── ParseListBeanTest.java
│           │                   ├── ResultSourceTypeTest.java
│           │                   └── ToMockResultTest.java
│           └── resources/
│               ├── api2doc/
│               │   ├── demo3/
│               │   │   ├── 1-项目简介.md
│               │   │   ├── 11-接口1的补充说明.md
│               │   │   ├── 2-技术架构.md
│               │   │   ├── 21-接口2的补充说明.md
│               │   │   └── 3-应用场景.md
│               │   └── welcome.md
│               └── application.yml
├── commons-armq/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── armq/
│       │                       ├── ArmqConfig.java
│       │                       ├── ConsumerConfig.java
│       │                       ├── MessageConsumer.java
│       │                       ├── MessageEntity.java
│       │                       ├── MessageService.java
│       │                       └── impl/
│       │                           ├── MessageConsumerTask.java
│       │                           ├── MessageConsumerTransfer.java
│       │                           └── MessageServiceImpl.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           └── commons/
│           │               └── test/
│           │                   └── armq/
│           │                       ├── ArmqTestApp.java
│           │                       ├── Normal.java
│           │                       ├── NormalTopicTest.java
│           │                       ├── Producer.java
│           │                       └── SendTest.java
│           └── resources/
│               └── .gitignore
├── commons-dsql/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── dsql/
│       │                       ├── DsqlExecutor.java
│       │                       ├── DsqlModifying.java
│       │                       ├── DsqlQuery.java
│       │                       ├── DsqlRepository.java
│       │                       ├── EnableDsqlRepositories.java
│       │                       ├── QueryBean.java
│       │                       ├── config/
│       │                       │   └── DsqlConfiguration.java
│       │                       └── impl/
│       │                           ├── CompositeBeanRowMapper.java
│       │                           ├── DsqlBuilder.java
│       │                           ├── DsqlExecutorImpl.java
│       │                           ├── DsqlRepositoryBeanFactory.java
│       │                           ├── DsqlRepositoryConfigRegistrar.java
│       │                           ├── DsqlRepositoryProxy.java
│       │                           └── SqlInfo.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       ├── demo/
│                       │   └── dsql/
│                       │       ├── Address.java
│                       │       ├── AddressDAO.java
│                       │       ├── AddressDistance.java
│                       │       ├── AddressDistanceDAO.java
│                       │       ├── AddressQuery.java
│                       │       ├── address-count.sql.ftl
│                       │       ├── address-delete-nearest.sql.ftl
│                       │       ├── address-list.sql.ftl
│                       │       ├── address-nearest-2.sql.ftl
│                       │       ├── address-nearest.sql.ftl
│                       │       ├── address-update-nearest.sql.ftl
│                       │       ├── appdsql/
│                       │       │   └── DsqlDemoApplication.java
│                       │       └── appjpa/
│                       │           └── JpaDemoApplication.java
│                       └── test/
│                           └── dsql/
│                               ├── BaseDsqlTest.java
│                               ├── DsqlAutoTest.java
│                               ├── DsqlModifyingTest.java
│                               ├── DsqlQueryTest.java
│                               ├── dao/
│                               │   ├── Location.java
│                               │   ├── LocationDAO.java
│                               │   └── LocationQuery.java
│                               ├── dao1/
│                               │   ├── LocationDsqlDAO.java
│                               │   ├── delete-nearest.sql.ftl
│                               │   └── update-nearest.sql.ftl
│                               ├── dao2/
│                               │   ├── LocationDistance.java
│                               │   ├── LocationDistanceDAO.java
│                               │   ├── location-nearest.sql.ftl
│                               │   └── locations.sql.ftl
│                               ├── dao3/
│                               │   ├── DistancedLocation.java
│                               │   ├── DistancedLocationDAO.java
│                               │   ├── location-count.sql.ftl
│                               │   └── locations.sql.ftl
│                               └── dao4/
│                                   ├── LocationAutoDAO.java
│                                   ├── countLocation.sql.ftl
│                                   ├── getLocations.sql.ftl
│                                   └── getNearestLocation.sql.ftl
├── commons-hedis/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               ├── commons/
│       │               │   └── hedis/
│       │               │       ├── cache/
│       │               │       │   ├── CacheService.java
│       │               │       │   ├── JedisCacheService.java
│       │               │       │   └── RedisTemplateCacheService.java
│       │               │       ├── config/
│       │               │       │   ├── EnableHedis.java
│       │               │       │   └── HedisConfiguration.java
│       │               │       ├── dschedule/
│       │               │       │   ├── DScheduling.java
│       │               │       │   ├── DSchedulingAspect.java
│       │               │       │   ├── JobExeInfo.java
│       │               │       │   └── ScheduleContext.java
│       │               │       └── dsyn/
│       │               │           ├── DSynchArgs.java
│       │               │           ├── DSynchronized.java
│       │               │           ├── DSynchronizedAspect.java
│       │               │           └── Server.java
│       │               └── mock/
│       │                   └── hedis/
│       │                       ├── MockCacheService.java
│       │                       └── MockHedisConfig.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       ├── demo/
│                       │   └── hedis/
│                       │       ├── CountService.java
│                       │       ├── DSynchronizedCountService.java
│                       │       ├── DemoCacheService.java
│                       │       ├── HedisDemoApp.java
│                       │       ├── LoopIncrementJob.java
│                       │       └── User.java
│                       └── test/
│                           └── hedis/
│                               ├── BaseSpringBootTest.java
│                               ├── BaseTestExecutionListener.java
│                               ├── CacheAnnoTest.java
│                               ├── JedisCacheServiceTest.java
│                               ├── MockitoInitializer.java
│                               ├── RedisTestConfig.java
│                               ├── RedissonClientTest.java
│                               ├── SchedulingApplication.java
│                               └── dsyn/
│                                   ├── BaseCacheTest.java
│                                   ├── CacheTestApplication.java
│                                   ├── CountService.java
│                                   ├── DSynchronizedService.java
│                                   ├── DSynchronizedTest.java
│                                   ├── Home.java
│                                   └── HomeService.java
├── commons-hi/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── hi/
│       │                       ├── Action.java
│       │                       ├── ApacheHttpClientBuilder.java
│       │                       ├── Api2DocSupport.java
│       │                       ├── AssertResponseFailedException.java
│       │                       ├── HttpClient.java
│       │                       ├── HttpClientListener.java
│       │                       ├── HttpErrorCode.java
│       │                       ├── HttpErrorCode.properties
│       │                       ├── HttpException.java
│       │                       ├── HttpRequest.java
│       │                       ├── Param.java
│       │                       ├── Request.java
│       │                       ├── Response.java
│       │                       ├── Session.java
│       │                       ├── WrappedResponse.java
│       │                       ├── Write.java
│       │                       └── WriteTo.java
│       └── test/
│           └── java/
│               ├── application.yml
│               ├── com/
│               │   └── terran4j/
│               │       ├── demo/
│               │       │   └── hi/
│               │       │       ├── Calculator.java
│               │       │       ├── CalculatorController.java
│               │       │       ├── HttpClientApp.java
│               │       │       └── demo.json
│               │       └── test/
│               │           └── hi/
│               │               ├── BaseHiTest.java
│               │               ├── HttpClientTest.java
│               │               ├── HttpClientTest.json
│               │               ├── TestHiApp.java
│               │               ├── api2doc/
│               │               │   ├── Api2DocApp.java
│               │               │   ├── Api2DocDemoController.java
│               │               │   ├── Api2DocSupportTest.java
│               │               │   └── MultiplyObject.java
│               │               └── exe/
│               │                   ├── ExeController.java
│               │                   ├── ExeTest.java
│               │                   ├── ExeTest.json
│               │                   └── PlusObject.java
│               ├── example.json
│               ├── hi.json
│               └── http.config.json
├── commons-jfinger/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── jfinger/
│       │       │               ├── Command.java
│       │       │               ├── CommandDefine.java
│       │       │               ├── CommandErrorCode.java
│       │       │               ├── CommandException.java
│       │       │               ├── CommandExecutor.java
│       │       │               ├── CommandGroup.java
│       │       │               ├── CommandGroupDefine.java
│       │       │               ├── CommandGroups.java
│       │       │               ├── CommandInterpreter.java
│       │       │               ├── CommandOption.java
│       │       │               ├── CommandOptionDefine.java
│       │       │               ├── CommandOptionType.java
│       │       │               ├── EnableJFinger.java
│       │       │               ├── Encoding.java
│       │       │               ├── JFingerConfiguration.java
│       │       │               ├── OptionType.java
│       │       │               ├── builtin/
│       │       │               │   ├── LogCommand.java
│       │       │               │   ├── SpringCommand.java
│       │       │               │   └── SystemCommand.java
│       │       │               └── impl/
│       │       │                   ├── BackCommandException.java
│       │       │                   ├── CommandInterpreterImpl.java
│       │       │                   ├── CommandLineApplicationListener.java
│       │       │                   ├── CommandLineService.java
│       │       │                   ├── CommandLineTask.java
│       │       │                   ├── DynMethodCommandExecutor.java
│       │       │                   └── Util.java
│       │       └── error.properties
│       └── test/
│           └── java/
│               ├── cmd.txt
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── commons/
│                               └── jfinger/
│                                   └── JFingerTestApplication.java
├── commons-reflux/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── reflux/
│       │                       ├── EnableReflux.java
│       │                       ├── Message.java
│       │                       ├── OnMessage.java
│       │                       ├── RefluxClient.java
│       │                       ├── RefluxErrorCode.java
│       │                       ├── RefluxServer.java
│       │                       ├── Reply.java
│       │                       ├── client/
│       │                       │   ├── ClientConnection.java
│       │                       │   ├── EnableRefluxClient.java
│       │                       │   ├── MessageHandler.java
│       │                       │   ├── RefluxClientConfiguration.java
│       │                       │   └── RefluxClientImpl.java
│       │                       └── server/
│       │                           ├── ClientAppInfo.java
│       │                           ├── ClientConnectionInfo.java
│       │                           ├── EnableRefluxServer.java
│       │                           ├── RefluxServerConfiguration.java
│       │                           ├── RefluxServerEndpoint.java
│       │                           └── RefluxServerImpl.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── commons/
│                               └── reflux/
│                                   ├── Hello.java
│                                   ├── RefluxApplication.java
│                                   ├── SendAndReceiveTest.java
│                                   └── TestServerEndpoint.java
├── commons-restpack/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── restpack/
│       │   │                   ├── EnableRestPack.java
│       │   │                   ├── HttpResult.java
│       │   │                   ├── HttpResultConverter.java
│       │   │                   ├── Log.java
│       │   │                   ├── LogItem.java
│       │   │                   ├── PageResult.java
│       │   │                   ├── RestPackController.java
│       │   │                   ├── RestPackIgnore.java
│       │   │                   ├── ServletUtils.java
│       │   │                   ├── config/
│       │   │                   │   └── RestPackConfiguration.java
│       │   │                   ├── impl/
│       │   │                   │   ├── DateConverter.java
│       │   │                   │   ├── ExceptionHolder.java
│       │   │                   │   ├── HttpAroundHandler.java
│       │   │                   │   ├── HttpErrorHandler.java
│       │   │                   │   ├── HttpResultMapper.java
│       │   │                   │   ├── RestPackAdvice.java
│       │   │                   │   ├── RestPackAspect.java
│       │   │                   │   ├── RestPackConfig.java
│       │   │                   │   ├── RestPackMessageConverter.java
│       │   │                   │   └── RestPackUtils.java
│       │   │                   └── log/
│       │   │                       ├── RestPackLogAppender.java
│       │   │                       └── RestPackLogAspect.java
│       │   └── resources/
│       │       └── restpack/
│       │           └── freemarker.properties
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           ├── demo/
│           │           │   └── restpack/
│           │           │       ├── DemoHttpResultConverter.java
│           │           │       ├── HelloBean.java
│           │           │       ├── HelloController.java
│           │           │       ├── RestPackDemoApp.java
│           │           │       ├── RestPackDemoAspect.java
│           │           │       ├── RestPackDemoController.java
│           │           │       └── RestPackErrorController.java
│           │           └── test/
│           │               └── restpack/
│           │                   ├── HttpResultConverterTest.java
│           │                   ├── HttpResultMapperTest.java
│           │                   ├── NoHttpResultConverterTest.java
│           │                   └── RestPackTest.java
│           └── resources/
│               ├── application.yml
│               ├── logback.xml
│               ├── static/
│               │   └── restpack/
│               │       └── hello.css
│               └── templates/
│                   └── restpack/
│                       └── hello.ftl
├── commons-test/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── test/
│       │                       ├── BaseHttpTest.java
│       │                       ├── BaseSpringBootTest.java
│       │                       ├── BaseTestExecutionListener.java
│       │                       ├── DatabaseInitializer.java
│       │                       ├── DatabaseTestConfig.java
│       │                       ├── ExtAssert.java
│       │                       ├── MockitoInitializer.java
│       │                       ├── RedisTestConfig.java
│       │                       ├── SigListener.java
│       │                       ├── TruncateTable.java
│       │                       ├── database.properties
│       │                       └── redis.properties
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── commons/
│                           └── test/
│                               ├── HelloService.java
│                               ├── MockitoTest.java
│                               └── TestApp.java
├── commons-util/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── util/
│       │       │               ├── Arrays.java
│       │       │               ├── Beans.java
│       │       │               ├── Checker.java
│       │       │               ├── Classes.java
│       │       │               ├── DateTimes.java
│       │       │               ├── Encoding.java
│       │       │               ├── Enums.java
│       │       │               ├── Expressions.java
│       │       │               ├── Files.java
│       │       │               ├── IOUtils.java
│       │       │               ├── IdWorker.java
│       │       │               ├── Jsons.java
│       │       │               ├── Maths.java
│       │       │               ├── Objects.java
│       │       │               ├── Randoms.java
│       │       │               ├── Server.java
│       │       │               ├── Strings.java
│       │       │               ├── config/
│       │       │               │   ├── ConfigElement.java
│       │       │               │   ├── JsonConfigElement.java
│       │       │               │   └── XmlConfigElement.java
│       │       │               ├── error/
│       │       │               │   ├── AuthorizedException.java
│       │       │               │   ├── BusinessException.java
│       │       │               │   ├── CommonErrorCode.java
│       │       │               │   ├── ErrorCode.java
│       │       │               │   ├── ErrorCodes.java
│       │       │               │   ├── ErrorMessage.java
│       │       │               │   ├── ErrorReport.java
│       │       │               │   ├── ResourceErrorCode.java
│       │       │               │   ├── SimpleErrorCode.java
│       │       │               │   └── null.properties
│       │       │               ├── reflect/
│       │       │               │   └── InterfaceFilter.java
│       │       │               ├── security/
│       │       │               │   ├── AsymmetricKeys.java
│       │       │               │   ├── MD5Util.java
│       │       │               │   └── Security.java
│       │       │               ├── task/
│       │       │               │   └── LoopExecuteTask.java
│       │       │               ├── value/
│       │       │               │   ├── JsonValueSource.java
│       │       │               │   ├── KeyedList.java
│       │       │               │   ├── MapValueSource.java
│       │       │               │   ├── ResourceBundlesProperties.java
│       │       │               │   ├── RichProperties.java
│       │       │               │   ├── ValueSource.java
│       │       │               │   ├── ValueSources.java
│       │       │               │   └── ValueWrapper.java
│       │       │               └── web/
│       │       │                   ├── Cookies.java
│       │       │                   └── IPAddresses.java
│       │       └── error.properties
│       └── test/
│           └── java/
│               ├── com/
│               │   └── terran4j/
│               │       └── common/
│               │           └── util/
│               │               ├── ClassesTest.java
│               │               ├── DateTimesTest.java
│               │               ├── EnumsTest.java
│               │               ├── ExpressionsTest.java
│               │               ├── JsonConfigElementTest.java
│               │               ├── JsonConfigElementTest.json
│               │               ├── JsonsTest.java
│               │               ├── LoopExecuteTaskTest.java
│               │               ├── SecurityTest.java
│               │               ├── StringsTest.java
│               │               ├── ValueTest.java
│               │               └── error/
│               │                   ├── BusinessExceptionTest.java
│               │                   ├── MockErrorCode.java
│               │                   ├── MockException.properties
│               │                   └── testGetReport.txt
│               └── error.properties
├── commons-website/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── website/
│       │   │                   ├── config/
│       │   │                   │   ├── Readme.java
│       │   │                   │   └── WebsiteConfiguration.java
│       │   │                   └── controller/
│       │   │                       └── WelcomeController.java
│       │   └── resources/
│       │       └── static/
│       │           └── website/
│       │               ├── flexible-lite/
│       │               │   └── flexible-lite-1.0.js
│       │               ├── less/
│       │               │   └── less-1.7.0.js
│       │               └── vue/
│       │                   └── vue-2.5.10.js
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── website/
│                               ├── HelloController.java
│                               └── MainApp.java
├── pom.xml
└── version.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================

/target/

# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea/

*.iml


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.


================================================
FILE: README.md
================================================

## 项目简介

本项目采用 SpringBoot 框架构建,致力于为 SpringBoot 应用程序的开发提升开发效率及编程体验。

本项目由多个子项目组成,每个子项目聚焦解决一个问题。
这里先简单介绍下这些子项目:
* [commons-api2doc](https://github.com/terran4j/commons/tree/master/commons-api2doc):  
    简称 Api2Doc,是一款 Http API 文档自动化生成工具,
    它通过反射的方式,读取 Controller 类的信息,
    然后自动生成易于阅读的在线 API 文档,节省开发者手工编写 API 文档的工作量。
* [commons-restpack](https://github.com/terran4j/commons/tree/master/commons-restpack):  
    简称 RestPack,是一款 Http API 数据包装框架,
    它可以将 Http API 的返回结果包装成统一的报文格式。
* [commons-dsql](https://github.com/terran4j/commons/tree/master/commons-dsql):  
    简称 DSQL,是一款从 SQL 到对象的自动映射框架,它尤其擅长动态复杂 SQL 的处理。
    它结合了现在两大主流持久层框架 JPA 及 MyBatis 的优点,
    从而更进一步的提高了持久层的开发效率。
* [commons-hedis](https://github.com/terran4j/commons/tree/master/commons-hedis):  
    简称 Hedis,是 Happy for using Redis 之意,目标是让 Redis 使用起来更容易。
    Hedis 集成了 spring-data-redis, Jedis,Redisson 等 Redis 客户端框架,
    并用它们解决一些具体的问题,如:分布式同步、轻量级分布式定时调度等。 
    

## 适用用户

适合有 Java / Kotlin + SpringBoot 开发经验的开发者们使用。

如果您有 Java 开发经验但对Spring Boot 还不熟悉的话,建议先阅读笔者写过的一本书
[《Spring Boot 快速入门》](http://www.jianshu.com/nb/14688855?order_by=seq)。
这本书的目标是帮助有 Java 开发经验的程序员们快速掌握 Spring Boot 开发技巧,
感受到 Spring Boot 的极简开发风格及超爽编程体验。


## 软件版本

本项目中所用到的基础软件,均基于以下版本构建:
* Java:  1.8
* Maven:  3.3.9
* SpringBoot:  1.5.9.RELEASE

本项目及所有子项目均在以上版本测试过,可以正常运行。
其它版本理论上相同,应该没啥区别,若遇到问题,欢迎反馈!


================================================
FILE: build.txt
================================================

## 统一修改版本号
mvn versions:set "-DnewVersion=1.0.2-SNAPSHOT"
mvn versions:commit

## 当版本为 SNAPSHOT 时的测试:
mvn clean test

## 当版本为 SNAPSHOT 时的部署:
mvn clean deploy -DskipTests

## 本地构建打包。
mvn clean install -DskipTests

## 所有项目一起部署太慢了,容易失败,所有分开部署:
## 建议在早上 10:00 以后执行(这会美国是晚上,网络稍好点)
mvn clean deploy -DskipTests -P release -pl commons-util -am     // 03:33
mvn clean deploy -DskipTests -P release -pl commons-website     // 02:27
mvn clean deploy -DskipTests -P release -pl commons-restpack    // 02:11
mvn clean deploy -DskipTests -P release -pl commons-api2doc     // 12:58
mvn clean deploy -DskipTests -P release -pl commons-hedis         // 03:05
mvn clean deploy -DskipTests -P release -pl commons-hi               // 03:12
mvn clean deploy -DskipTests -P release -pl commons-test            // 02:00
mvn clean deploy -DskipTests -P release -pl commons-dsql           // 03:14

================================================
FILE: commons-api2doc/.gitignore
================================================
/target/
/.settings/
/.classpath
/.project
*.iml


================================================
FILE: commons-api2doc/README.md
================================================

本文介绍一个非常好用的自动化生成 Restful API 文档的工具——Api2Doc
它基于 SpringBoot ,原理类似于 Swagger2,但比 Swagger2 要简单好用。

此项目已经放到 github 中,需要源码的朋友请点击
[这里](https://github.com/terran4j/commons/tree/master/commons-api2doc)

## 目录

* 项目背景
* Api2Doc 简介
* 引入 Api2Doc 依赖
* 启用 Api2Doc 服务
* 给 Controller 类上添加文档注解
* @Api2Doc 注解详述
* @ApiComment 注解详述
* @ApiError 注解详述
* 给文档菜单项排序
* 补充自定义文档
* 定制文档的欢迎页
* 定制文档的标题及图标
* 关闭 Api2Doc 服务
* 后续开发计划

## 项目背景

在互联网/移动互联网软件的研发过程中,大多数研发团队前后台分工是非常明确的,
后台工程师负责服务端系统的开发,一般是提供 HTTP/HTTPS 的 Restful API 接口,
前端工程师则负责 Android、iOS、H5页面的开发,需要调用 Restful API 接口。

这就需要有一套 Restful API 文档,以帮助两方在 API 接口进行沟通,并达成一致意见。
一般情况下,编写文档的工作都会落在后台工程师身上,毕竟 API 是他们提供的嘛。

但问题是,编写 Restful API 文档是一件既繁琐、又费时、还对提高技术能力没啥帮助的苦差事,
尤其在是快速迭代、需求频繁修改的项目中,改了代码还要同步改文档,
哪点改错了或改漏了都可能产生前后端实现的不一致,导致联调时发现 BUG,
这个锅最终还是要后台工程师来背(宝宝心里苦啊...)。

因此,业界就出现了一些**根据代码自动生成 Restful API 文档**的开源项目,
与 Spring Boot 结合比较好的是 Swagger2,Swagger2 通过读取 Controller 
代码中的注解信息,来自动生成 API 文档,可以节省大量的手工编写文档的工作量。

本项目作者之前也是用的 Swagger2,但发现 Swagger2 也有好多地方用得不爽:

第一,**Swagger2 的注解非常臃肿**,我们看下这段代码:

```java

@RestController
@RequestMapping(value = "/user3")
public class UserController2Swagger2 {

    @ApiOperation(value = "获取指定id用户详细信息",
            notes = "根据user的id来获取用户详细信息",
            httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", value = "用户名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "用户密码",
                    paramType = "query", required = true, dataType = "String")
    })
    @RequestMapping(name = "用户注册", value = "/regist",
            method = RequestMethod.GET)
    public UserInfo regist(@RequestParam("userName") String userName,
                           @RequestParam("password") String password) {
        return new UserInfo();
    }
}
```

@ApiOperation、@ApiImplicitParam 都是 Swagger2 提供的注解,用于定义 API 信息。
其实,API 方法本身就包含了很多信息,如HTTP Method、参数名、参数类型等等,
像 @ApiImplicitParam 中除了 value 属性有用外,其它都是重复描述。


第二,Swagger2 的页面排版不太友好,它是一个垂直排列的方式,不利于信息的展示。
并且看 API 详细信息还要一个个展开,中间还夹杂着测试的功能,反正作为文档是不易于阅读;
至于作为测试工具嘛...,现在专业的测试工具也有很多,测试人员好像也不选它。

第三,Swagger2 还有好多细节没做好,比如看这个图:

![swgger2-1.png](http://upload-images.jianshu.io/upload_images/4489584-575b3f94d746d921.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

红框中的 API 其实对应的是同一个方法,之所以有这么多,只是因为写这个方法
时没有指定 method:

```java
@RestController
@RequestMapping(value = "/user2")
public class UserController2Swagger2 {
    
    @RequestMapping(value = "/do_something")
    public void doSomethingRequiredLogon() {
    }
    
    // 其它方法,这里省略...
}
``` 

(当没指定 method 时,Spring Boot 会默认让这个接口支持所有的 method)

因此,考虑到与其长长久久忍受 Swagger2 的各种不爽,不如花些时间做一个
更好用的“自动化文档系统”,于是就诞生了本项目: Api2Doc 。 


## Api2Doc 简介

Api2Doc 专注于 Restful API 文档的自动生成,它的原理与 Swagger2 是类似的,
都是通过反射,分析 Controller 中的信息生成文档,但它要比 Swagger2 好很多。

最大的不同是: **Api2Doc 比 Swagger2 要少写很多代码**。

举个例子,使用 Swagger2 的代码是这样的:

```java

@RestController
@RequestMapping(value = "/user")
public class UserController {

    @ApiOperation(value = "添加用户", httpMethod = "POST",
            notes = "向用户组中添加用户,可以指定用户的类型")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "group", value = "用户组名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "name", value = "用户名",
                    paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name = "type", value = "用户类型",
                                paramType = "query", required = true, dataType = "String")
    })
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public User addUser(String group, String name, String type) {
        return null; // TODO:  还未实现。
    }
}
```

我们看下使用 Api2Doc 注解修饰后的代码:

```java
@Api2Doc(id = "users")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo2")
public class UserController2 {

    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name, String type) {
        return null; // TODO:  还未实现。
    }
    
    // 其它方法,这里省略...
}
```

看,Api2Doc 仅需要在方法上加上 @Api2Doc @ApiComment 注解等极少数代码,
但它生成的文档可一点不含糊,如下图所示:

![api2doc-2-1.png](http://upload-images.jianshu.io/upload_images/4489584-98f94cb360c0ccde.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![api2doc-2-2.png](http://upload-images.jianshu.io/upload_images/4489584-fedf2897f5c217b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

有的朋友可能会觉得很奇怪:文档页面上的说明、示例值等内容,在代码中没有写啊,
这些是哪来的呢?

这里涉及到 Api2Doc 的核心设计理念,就是:它尽可能通过智能分析,自动收集
生成文档所需的信息,从而**让用户少写代码**。

说得有点抽象哈,下面我们来正面回答这个问题,请大家注意这个类上有一个注解:

```
@ApiComment(seeClass = User.class)
```

它意思是: 在 API 方法上遇到没写说明信息时,请参照 User 类中的定义的说明信息。

下面是 User 类的代码:

```java
public class User {

    @ApiComment(value = "用户id", sample = "123")
    private Long id;

    @ApiComment(value = "用户名", sample = "terran4j")
    private String name;

    @ApiComment(value = "账号密码", sample = "sdfi23skvs")
    private String password;

    @ApiComment(value = "用户所在的组", sample = "研发组")
    private String group;

    @ApiComment(value = "用户类型", sample = "admin")
    private UserType type;

    @ApiComment(value = "是否已删除", sample = "true")
    @RestPackIgnore
    private Boolean deleted;

    @ApiComment(value = "创建时间\n也是注册时间。")
    private Date createTime;

    // 省略  getter / setter 方法。
}
```

大家看明白了没? API 方法中的参数,如果与 User 类的属性同名的话,就用类
属性的 @ApiComment 说明信息自动填充。

其实这也符合实际的业务逻辑。因为在大部分项目中,有的字段会在多个实体类、
多个 API 方法中用到,完全没有必要重复编写其说明信息,只要有一个地方定义好了,
然后其它地方参照就行了。

当然,这只是 Api2Doc 比 Swagger2 好用的特性之一,还有不少比 Swagger2 好用的地方。

下面我们就来全面讲解它的用法,希望可以帮助开发者们从文档编写的苦海中解脱出来。


## 引入 Api2Doc 依赖

如果是 maven ,请在 pom.xml 中添加依赖,如下所示:

```xml
        <dependency>
            <groupId>com.github.terran4j</groupId>
            <artifactId>terran4j-commons-api2doc</artifactId>
            <version>${api2doc.version}</version>
        </dependency>
```

如果是 gradle,请在 build.gradle 中添加依赖,如下所示:

```groovy
compile "com.github.terran4j:terran4j-commons-api2doc:${api2doc.version}"
```

${api2doc.version} **最新稳定版,请参考 [这里](https://github.com/terran4j/commons/blob/master/version.md)**


## 启用 Api2Doc 服务

本教程的示例代码在 src/test/java 目录的 com.terran4j.demo.api2doc 中,
您也可以从 [这里](https://github.com/terran4j/commons/tree/master/commons-api2doc/src/test/java/com/terran4j/demo/api2doc) 获取到。

首先,我们需要在有 @SpringBootApplication 注解的类上,添加 @EnableApi2Doc 
注解,以启用 Api2Doc 服务,如下代码所示:

```java
package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.config.EnableApi2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//  文档访问地址: http://localhost:8080/api2doc/home.html
@EnableApi2Doc
@SpringBootApplication
public class Api2DocDemoApp {

    public static void main(String[] args) {
        SpringApplication.run(Api2DocDemoApp.class, args);
    }

}
``` 

## 给 Controller 类上添加文档注解

然后我们在 RestController 类添加 @Api2Doc 注解,在需要有文档说明的地方
添加 @ApiComment 注解即可,如下所示:

```java
package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@Api2Doc(id = "demo1", name = "用户接口1")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo1")
public class UserController1 {

    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name,
                        @ApiComment("用户类型") UserType type) {
        return null; // TODO:  还未实现。
    }
}
```

这个方法的返回类型 User 类的定义为:

```java
public class User {

    @ApiComment(value = "用户id", sample = "123")
    private Long id;

    @ApiComment(value = "用户名", sample = "terran4j")
    private String name;

    @ApiComment(value = "账号密码", sample = "sdfi23skvs")
    private String password;

    @ApiComment(value = "用户所在的组", sample = "研发组")
    private String group;

    @ApiComment(value = "用户类型", sample = "admin")
    private UserType type;

    @ApiComment(value = "是否已删除", sample = "true")
    @RestPackIgnore
    private Boolean deleted;

    @ApiComment(value = "创建时间\n也是注册时间。")
    private Date createTime;

    // 省略  getter / setter 方法。
}
```

以及 type 属性的类型,也就是 UserType 类的定义为:

```java
package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.ApiComment;

public enum UserType {

    @ApiComment("管理员")
    admin,

    @ApiComment("普通用户")
    user
}
```

编写好代码后,我们运行 main 函数,访问 Api2Doc 的主页面:

```
http://localhost:8080/api2doc/home.html
```

文档页面如下:

![api2doc-3-1.png](http://upload-images.jianshu.io/upload_images/4489584-ef8f5a56917da47f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![api2doc-3-2.png](http://upload-images.jianshu.io/upload_images/4489584-55ea3a295a009855.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

说明 Api2Doc 服务起作用了,就是这么简单!


## @Api2Doc 注解详述

Api2Doc 一共有 3 个注解:@Api2Doc、@ApiComment 及 @ApiError 。

@Api2Doc 用于对文档的生成进行控制。

@Api2Doc 修饰在类上,表示这个类会参与到文档生成过程中,Api2Doc 服务
会扫描 Spring 容器中所有的 Controller 类,只有类上有 @Api2Doc 的类,
才会被生成文档,一个类对应于文档页面左侧的一级菜单项,@Api2Doc 的 
name 属性则表示这个菜单项的名称。

@Api2Doc 也可以修饰在方法,不过在方法上的  @Api2Doc 通常是可以省略,
 Api2Doc 服务会扫描这个类的所有带有 @RequestMapping 的方法,
 每个这样的方法对应文档页面的左侧的二级菜单项, 菜单项的名称取 
 @RequestMapping 的 name 属性,当然您仍然可以在方法上用  @Api2Doc 
 的 name 属性进行重定义。
 
 
 ## @ApiComment 注解详述
 
 @ApiComment 用于对 API 进行说明,它可以修饰在很多地方:
 * 修饰在类上,表示对这组 API 接口进行说明;
 * 修饰在方法上,表示对这个 API 接口进行说明;
 * 修饰在参数上,表示对这个 API 接口的请求参数进行说明;
 * 修饰在返回类型的属性上,表示对这个 API 接口的返回字段进行说明;
 * 修饰在枚举项上,表示对枚举项进行说明;

如果相同名称、相同意义的属性或参数字段,其说明已经在别的地方定义过了,
可以用 @ApiComment 的 seeClass 属性表示采用指定类的同名字段上的说明信息,
所以如这段代码:

```java
@Api2Doc(id = "demo1", name = "用户接口1")
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo1")
public class UserController1 {

    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(String group, String name, UserType type) {
        return null; // TODO:  还未实现。
    }
}
```

虽然 group, name ,type 三个参数没有用 @ApiComment 进行说明,
但由于这个类上有 @ApiComment(seeClass = User.class) ,
因此只要 User 类中有 group, name ,type 字段并且有  @ApiComment 的说明就行了。


## @ApiError 注解详述

@ApiError 用于定义错误码,有的 API 方法在执行业务逻辑时会产生错误,
出错后会在返回报文包含错误码,以方便客户端根据错误码作进一步的处理,
因此也需要在 API 文档上体现错误码的说明。

如下代码演示了 @ApiError 的用法:

```java
@Api2Doc(id = "demo", name = "用户接口", order = 0)
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/src/test/resources/demo")
public class UserController {
    
    @Api2Doc(order = 50)
    @ApiComment("根据用户id,删除指定的用户")
    @ApiError(value = "user.not.found", comment = "此用户不存在!")
    @ApiError(value = "admin.cant.delete", comment = "不允许删除管理员用户!")
    @RequestMapping(name = "删除指定用户",
            value = "/user/{id}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("id") Long id) {
    }
}
```

@ApiError 的 value 属性表示错误码,comment 表示错误码的说明。

错误码信息会显示在文档的最后面,效果如下所示:

![api2doc-7.png](http://upload-images.jianshu.io/upload_images/4489584-44a77bbb3c1e84da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


## 给文档菜单项排序

我们可以用 @Api2Doc 中的 order 属性给菜单项排序,order 的值越小,
该菜单项就越排在前面,比如对于这段代码:

```java
package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Api2Doc(id = "demo2", name = "用户接口2", order = 1)
@ApiComment(seeClass = User.class)
@RestController
@RequestMapping(value = "/api2doc/demo2")
public class UserController2 {

    @Api2Doc(order = 10)
    @ApiComment("添加一个新的用户。")
    @RequestMapping(name = "新增用户",
            value = "/user", method = RequestMethod.POST)
    public User addUser(
            @ApiComment("用户组名称") String group,
            @ApiComment("用户名称") String name,
            @ApiComment("用户类型") UserType type) {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 20)
    @ApiComment("根据用户id,查询此用户的信息")
    @RequestMapping(name = "查询单个用户",
            value = "/user/{id}", method = RequestMethod.GET)
    public User getUser(@PathVariable("id") Long id) {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 30)
    @ApiComment("查询所有用户,按注册时间进行排序。")
    @RequestMapping(name = "查询用户列表",
            value = "/users", method = RequestMethod.GET)
    public List<User> getUsers() {
        return null; // TODO:  还未实现。
    }

    @Api2Doc(order = 40)
    @ApiComment("根据指定的组名称,查询该组中的所有用户信息。")
    @RequestMapping(name = "查询用户组",
            value = "/group/{group}", method = RequestMethod.GET)
    public UserGroup getGroup(@PathVariable("group") String group) {
        return null; // TODO:  还未实现。
    }
}
```

显示的结果为:

![api2doc-3.png](http://upload-images.jianshu.io/upload_images/4489584-0818fdef543c8c07.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

在类上的 @Api2Doc 同样可以给一级菜单排序,规则是一样的,这里就不演示了。


## 补充自定义文档

有时候光有自动生成的 API 文档似乎还不太完美,或许我们想补充点别的什么东西,
比如: 对项目的背景介绍、技术架构说明之类,那这个要怎么弄呢?

Api2Doc 允许用 md 语法手工编写文档,并集成到自动生成的 API 文档之中,方法如下:

首先,要在类上的 @Api2Doc 定义 id 属性,比如对下面这个类:

```java
package com.terran4j.demo.api2doc;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api2Doc(id = "demo3", name = "用户接口3")
@RestController
@RequestMapping(value = "/api2doc/demo3")
public class UserController3 {

    @Api2Doc(order = 10)
    @RequestMapping(name = "接口1", value = "/m1")
    public void m1() {
    }

    @Api2Doc(order = 20)
    @RequestMapping(name = "接口2", value = "/m2")
    public void m2() {
    }
}
``` 

@Api2Doc(id = "demo3", name = "用户接口3") 表示:对应的一级菜单“用户接口3”
的 id 为 demo3。

然后,我们在 src/main/resources 中创建目录  api2doc/demo3,
前面的 api2doc 是固定的,后面的 demo3 表示这个目录中的文档是添加到
id 为 demo3 的一级文档菜单下。

然后我们在 api2doc/demo3 目录中编写 md 格式的文档,如下图所示:

![api2doc-4.png](http://upload-images.jianshu.io/upload_images/4489584-a76a84061f2771d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

文件名的格式为 ${order}-${文档名称}.md,即 - 号前面的数字表示这个文档的排序,
与 @Api2Doc 中的 order 属性是一样的,而 - 号后面是文档名称,也就是二级菜单的名称。

因此,最后文档的显示效果为:

![api2doc-5.png](http://upload-images.jianshu.io/upload_images/4489584-73814ce5bde91b2d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

看,手工编写的补充文档与自动生成的 API 文档,通过 order 进行排序组合在一起,
看起来毫无违和感。


## 定制文档的欢迎页

每次访问文档页面 http://localhost:8080/api2doc/home.html 时,
中间的内容是非常简单的一句:

```
欢迎使用 Api2Doc !
```

这似乎有点不太好,不过没关系,我们可以编写自己的欢迎页。

方法很简单,在 src/main/resources 目录的 api2doc 目录下,创建一个名为 
welcome.md 的文件(这个名称是固定的),然后用 md 语法编写内容就可以。


## 配置文档的标题及图标

可以在 application.yml 中配置文档的标题及图标,如下所示:

```yaml
api2doc:
  title: Api2Doc示例项目——接口文档
  icon: https://spring.io/img/homepage/icon-spring-framework.svg
```

图标为一个全路径 URL,或本站点相对路径 URL 都行。

配置后的显示效果为: 

![api2doc-6.png](http://upload-images.jianshu.io/upload_images/4489584-494a0c8042aaffb3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


## 关闭 Api2Doc 服务 

您在 application.yml 中配置 api2doc.enabled 属性,以开启或关闭 Api2Doc 服务,如:

```yaml
# 本地环境
api2doc:
  title: Api2Doc示例项目——接口文档
  icon: https://spring.io/img/homepage/icon-spring-framework.svg

---
# 线上环境
spring:
  profiles: online

api2doc:
  enabled: false
```

api2doc.enabled 为 false 表示关闭 Api2Doc 服务,不写或为 true 表示启用。

由于  Api2Doc 服务没有访问权限校验,建议您在受信任的网络环境(如公司内网)
中才启用 Api2Doc 服务。


## 后续开发计划

参见[后续开发计划](https://github.com/terran4j/commons/blob/master/commons-api2doc/doc/TODO.md)


================================================
FILE: commons-api2doc/doc/TODO.md
================================================

## 后续开发计划

Api2Doc 项目后续计划要开发的功能如下:

* 参数为对象,参数类型object,可以指出具体类型
* 可以导出为 html 格式的文档文件,可以离线浏览,
   支持在页面上手工操作导出,以及程序调用 API 自定义导出两种方式。
* 可以导出为 md 格式的文档文件,可以放到 md 运行环境中浏览,
   支持在页面上手工操作导出,以及程序调用 API 自定义导出两种方式。
* 对测试进行支持。
* 文档样式设计得更漂亮。
* 文档样式支持自定义。

### 1.0.2 (已发布于 2018-04-06 )

新增了以下功能:
1.  支持各种用 @XxxMapping 修饰的方法生成文档,包括:
         `@GetMapping`、
         `@PostMapping`、
         `@PutMapping`、
         `@DeleteMapping`、
         `@PatchMapping`;
     (之前只支持 `@RequestMapping` 。)
2. 支持各种形式的参数,包括:
         `@PathVariable`、
         `@RequestHeader`、
         `@CookieValue`、
         `@RequestPart`;
     (之前只支持 `@RequestParam` 。)
     并在文档页面的“请求参数”表格,加上“参数形式”这一列。
3.  文档页面,“URL示例”改为“请求示例”,
     请求示例为 curl 命令格式,并支持所有的 HTTP 方法 ,
    (之前是 URL 格式,并且只支持了 GET 方法)。
    
修复了以下 BUG:

1. 修复当返回类型为简单类型时未能显示在文档的 BUG。



================================================
FILE: commons-api2doc/doc/aboutCurl.md
================================================

## 什么是 curl
curl 是一款很强大的 http 命令行工具,可以的向服务端发起 HTTP/HTTPS 请求,
是一个很方便 HTTP API 测试手段。

## 如何安装 curl 
 - 如果是 Linux / MAC 系统,一般系统都自带了 curl (如果没有安装也很简单,请自行百度)。
 - 如果是 Windows 系统,建议先安装 Cygwin64 ,然后在 Cygwin64 中安装使用 curl 。
 
下面就介绍下如何使用 Cygwin64 包管理器安装 curl

Cygwin64 包管理器下载地址:
[http://www.cygwin.com/setup-x86_64.exe](http://www.cygwin.com/setup-x86_64.exe)

下载后运行,一直下一步到以下界面:

![image](http://upload-images.jianshu.io/upload_images/4489584-b4431f26c3440bd6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View 选择 Full,Search 后面输入:curl

然后点击第一行的Skip,点击下一步,后面就按默认的设置一步步安装即可。

================================================
FILE: commons-api2doc/pom.xml
================================================
<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">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>com.github.terran4j</groupId>
		<artifactId>terran4j-commons-parent</artifactId>
		<version>1.0.4-SNAPSHOT</version>
	</parent>

	<artifactId>terran4j-commons-api2doc</artifactId>
	<packaging>jar</packaging>
	<name>terran4j-commons-api2doc</name>
	<url>https://github.com/terran4j/commons</url>

	<dependencies>

        <!-- md 转 html 工具 -->
		<dependency>
		    <groupId>com.vladsch.flexmark</groupId>
		    <artifactId>flexmark</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.vladsch.flexmark</groupId>
		    <artifactId>flexmark-util</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.vladsch.flexmark</groupId>
		    <artifactId>flexmark-ext-tables</artifactId>
		</dependency>
        <dependency>
            <groupId>com.vladsch.flexmark</groupId>
            <artifactId>flexmark-ext-spec-example</artifactId>
        </dependency>

        <!-- 模板引擎 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

		<!-- terran4j 工具类库。 -->
		<dependency>
			<groupId>com.github.terran4j</groupId>
			<artifactId>terran4j-commons-util</artifactId>
		</dependency>
		<dependency>
			<groupId>com.github.terran4j</groupId>
			<artifactId>terran4j-commons-website</artifactId>
		</dependency>
        <dependency>
            <groupId>com.github.terran4j</groupId>
            <artifactId>terran4j-commons-restpack</artifactId>
        </dependency>

		<!-- aspectj -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
		</dependency>

		<!-- json -->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.module</groupId>
			<artifactId>jackson-module-jsonSchema</artifactId>
		</dependency>
    </dependencies>

</project>


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/Api2DocMocker.java
================================================
package com.terran4j.commons.api2doc;

import com.terran4j.commons.api2doc.impl.Api2DocObjectFactory;

import java.util.List;

public class Api2DocMocker {

    public static <T> T mockBean(Class<T> clazz) {
        return Api2DocObjectFactory.createBean(clazz);
    }

    public static <T> List<T> mockList(Class<T> clazz, int size) {
        return Api2DocObjectFactory.createList(clazz, size);
    }

    public static <T> T[] mockArray(Class<T> clazz, int size) {
        return Api2DocObjectFactory.createArray(clazz, size);
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/Api2Doc.java
================================================
package com.terran4j.commons.api2doc.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
public @interface Api2Doc {
	
	int DEFAULT_ORDER = 100;

	/**
	 * 文档的id。<br>
	 * 对于一个类中的重载方法,一定要用不同的 id 区分,不然会出错。
	 * 
	 * @return
	 */
	@AliasFor("value")
	String id() default "";

	/**
	 * 文档的id。<br>
	 * 对于一个类中的重载方法,一定要用不同的 id 区分,不然会出错。
	 * 
	 * @return
	 */
	@AliasFor("id")
	String value() default "";

	/**
	 * 是否忽略此文档。
	 * 
	 * @return
	 */
	boolean ignore() default false;

	/**
	 * 设置文档的排序。<br>
	 * 数字越小,排序越靠前。
	 * 
	 * @return
	 */
	int order() default DEFAULT_ORDER;
	
	String name() default "";

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiComment.java
================================================
package com.terran4j.commons.api2doc.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
		ElementType.TYPE,
		ElementType.METHOD,
		ElementType.PARAMETER,
		ElementType.FIELD,
})
public @interface ApiComment {

	String value() default "";

	String sample() default "";

	Class<?> seeClass() default Object.class;

	String seeField() default "";

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiError.java
================================================
package com.terran4j.commons.api2doc.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Repeatable(ApiErrors.class)
public @interface ApiError {

	String value();
	
	String comment() default "";
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiErrors.java
================================================
package com.terran4j.commons.api2doc.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface ApiErrors {

	ApiError[] value();
	
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeConfig.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import java.util.List;

import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiParamObject;

public class CodeConfig {

	public List<ApiParamObject> getExtraPrams(ApiDocObject doc) {
		return null;
	}

	private String pkgName;

	private String declaredComment;

	public String getPkgName() {
		return pkgName;
	}

	public void setPkgName(String pkgName) {
		this.pkgName = pkgName;
	}

	public String getDeclaredComment() {
		return declaredComment;
	}

	public void setDeclaredComment(String declareComment) {
		this.declaredComment = declareComment;
	}

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeOutput.java
================================================
package com.terran4j.commons.api2doc.codewriter;

public interface CodeOutput {

	void writeCodeFile(String fileName, String fileContent);
	
	void setPercent(int percent);
	
	void log(String log, String... args);
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeUtils.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import java.util.Set;

public class CodeUtils {

	public static final void addImport(Class<?> clazz, Set<String> imports) {
		if (clazz == null || clazz.getPackage() == null) {
			return;
		}

		String paramPkgName = clazz.getPackage().getName();

		if (paramPkgName.equals("java.lang")) {
			return;
		}

		if (paramPkgName.startsWith("java.") || paramPkgName.startsWith("javax.")) {
			imports.add(clazz.getName());
		}
	}
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/EnumCodeWriter.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import com.terran4j.commons.api2doc.impl.Api2DocUtils;
import com.terran4j.commons.api2doc.impl.ApiCommentUtils;
import com.terran4j.commons.api2doc.impl.FlexibleString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.impl.ClasspathFreeMarker;

import freemarker.template.Template;

@Service
public class EnumCodeWriter {
	
	private static final Logger log = LoggerFactory.getLogger(EnumCodeWriter.class);

	@Autowired
	private ClasspathFreeMarker classpathFreeMarker;

	private Template enumTemplate = null;

	@PostConstruct
	public void init() {
		try {
			enumTemplate = classpathFreeMarker.getTemplate(getClass(), //
					"enum.java.ftl");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	public void writeCode(Class<?> currentClass, String className, //
			CodeOutput out, CodeConfig config) throws Exception {
		
		if (currentClass == null || !currentClass.isEnum()) {
			return;
		}
		
		Map<String, Object> model = new HashMap<>();
		
		model.put("class", className);

		if (config == null) {
			config = new CodeConfig();
		}
		model.put("config", config);
		
		List<EnumInfo> enumInfos = new ArrayList<>();
		Class<Enum<?>> enumClass = (Class<Enum<?>>) currentClass;
		Enum[] enums = enumClass.getEnumConstants();
		for (Enum enumObject : enums) {
			
			EnumInfo enumInfo = new EnumInfo();
			
			String name = enumObject.name();
			enumInfo.setName(name);
			
			String comment = null;
			Field field = null;
			try {
				field = enumClass.getDeclaredField(name);
			} catch (NoSuchFieldException | SecurityException e1) {
				log.error("Can't get field \"" + name + "\" from Enum: " //
						+ enumClass.getName(), e1);
				continue;
			}
			ApiComment apiComment = field.getAnnotation(ApiComment.class);
			comment = ApiCommentUtils.getComment(
					apiComment, null, field.getName());
			if (comment != null) {
                comment = new FlexibleString(comment).javadoc(1);
            }
//			if (apiComment != null && StringUtils.hasText(apiComment.value())) {
//                comment = new FlexibleString(apiComment.value().trim()).javadoc(1);
//			}
			enumInfo.setComment(comment);
			
			enumInfos.add(enumInfo);
		}
		model.put("enums", enumInfos);
		
		String code = classpathFreeMarker.build(enumTemplate, model);
		out.writeCodeFile(className + ".java", code);
	}
	
	public static final class EnumInfo {
		
		private String comment;
		
		private String name;

		public String getComment() {
			return comment;
		}

		public void setComment(String comment) {
			this.comment = comment;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
		
	}
}



================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/FileCodeOutput.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import java.io.File;

import com.terran4j.commons.util.Files;

public class FileCodeOutput implements CodeOutput {
	
	private final String path;
	
	public FileCodeOutput(String path) {
		super();
		this.path = path;
	}

	@Override
	public void writeCodeFile(String fileName, String fileContent) {
		File file = new File(path + "/" + fileName);
		Files.writeFile(fileContent, file);
	}

	@Override
	public void setPercent(int percent) {
	}

	@Override
	public void log(String log, String... args) {
	}

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/JavaBeanCodeWriter.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import com.terran4j.commons.api2doc.domain.ApiDataType;
import com.terran4j.commons.api2doc.domain.ApiResultObject;
import com.terran4j.commons.api2doc.domain.DateConverter;
import com.terran4j.commons.api2doc.impl.ClasspathFreeMarker;
import freemarker.template.Template;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.*;

import static java.util.Locale.ENGLISH;

@Service
public class JavaBeanCodeWriter {

    private static final String GET_PREFIX = "get";

    private static final String SET_PREFIX = "set";

    private static final String IS_PREFIX = "is";

    @Autowired
    private ClasspathFreeMarker classpathFreeMarker;

    private Template javaBeanTemplate = null;

    @PostConstruct
    public void init() {
        try {
            javaBeanTemplate = classpathFreeMarker.getTemplate(getClass(), //
                    "bean.java.ftl");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void writeCode(ApiResultObject result, String className, //
                          CodeOutput out, CodeConfig config) throws Exception {

        List<ApiResultObject> children = result.getChildren();
        if (children == null || children.size() == 0) {
            return;
        }

        Map<String, Object> model = getModel(result, className, config);

        String code = classpathFreeMarker.build(javaBeanTemplate, model);

        out.writeCodeFile(className + ".java", code);
    }

    public Map<String, Object> getModel(ApiResultObject result, String className, //
                                        CodeConfig config) {

        Map<String, Object> model = new HashedMap<>();

        model.put("class", className);

        if (config == null) {
            config = new CodeConfig();
        }
        model.put("config", config);

        // java 类上的注释。
        String comment = result.getComment().javadoc(0);
        if (StringUtils.hasText(comment)) {
            model.put("comment", comment);
        }

        Set<String> imports = new HashSet<>();
        model.put("imports", imports);

        List<FieldInfo> fields = new ArrayList<FieldInfo>();
        List<ApiResultObject> children = result.getChildren();
        for (ApiResultObject child : children) {
            FieldInfo field = new FieldInfo();

            String name = child.getId();
            field.setName(name);

            String type = toTypeName(child);
            field.setType(type);

            String fieldComment = child.getComment().javadoc(1);
            if (StringUtils.hasText(fieldComment)) {
                field.setComment(fieldComment);
            }

            // Date 自动转成 Long 类型了。
            Class<?> sourceType = getSourceType(child);
            CodeUtils.addImport(sourceType, imports);

            boolean isBooleanClass = (child.getDataType() == ApiDataType.BOOLEAN);
            String getMethod = toGetMethodName(isBooleanClass, name);
            field.setGetMethod(getMethod);

            String setMethod = toSetMethodName(name);
            field.setSetMethod(setMethod);

            fields.add(field);
        }

        model.put("fields", fields);

        return model;
    }

    private String toGetMethodName(boolean isBooleanClass, String fieldName) {
        String baseName = getBaseName(fieldName);
        String methodName = null;
        if (isBooleanClass) {
            methodName = IS_PREFIX + baseName;
        } else {
            methodName = GET_PREFIX + baseName;
        }
        return methodName;
    }

    private String toSetMethodName(String fieldName) {
        String baseName = getBaseName(fieldName);
        String methodName = SET_PREFIX + baseName;
        return methodName;
    }

    private String getBaseName(String name) {
        return name.substring(0, 1).toUpperCase(ENGLISH) + name.substring(1);
    }

    private Class<?> getSourceType(ApiResultObject result) {
        Class<?> sourceType = result.getSourceType();
        return DateConverter.dateAsLongClass(sourceType);
    }

    private String toTypeName(ApiResultObject result) {
        ApiDataType dataType = result.getDataType();
        Class<?> sourceType = getSourceType(result);
        ;
        String typeName = sourceType.getSimpleName();
        if (dataType.isArrayType()) {
            typeName = typeName + "[]";
        }
        return typeName;
    }

    public static final class FieldInfo {

        private String type;

        private String name;

        private String comment;

        private String getMethod;

        private String setMethod;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        public String getGetMethod() {
            return getMethod;
        }

        public void setGetMethod(String getMethod) {
            this.getMethod = getMethod;
        }

        public String getSetMethod() {
            return setMethod;
        }

        public void setSetMethod(String setMethod) {
            this.setMethod = setMethod;
        }

    }
}



================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/MemoryCodeOutput.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MemoryCodeOutput implements CodeOutput {

	private final Map<String, String> codes = new ConcurrentHashMap<>();

	@Override
	public void writeCodeFile(String fileName, String fileContent) {
		codes.put(fileName, fileContent);
	}

	@Override
	public void setPercent(int percent) {
	}

	@Override
	public void log(String log, String... args) {
	}
	
	public String getCode(String fileName) {
		return codes.get(fileName);
	}
	
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/RetrofitCodeWriter.java
================================================
package com.terran4j.commons.api2doc.codewriter;

import com.terran4j.commons.api2doc.domain.*;
import com.terran4j.commons.api2doc.impl.ClasspathFreeMarker;
import com.terran4j.commons.util.Classes;
import com.terran4j.commons.util.value.KeyedList;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.collections4.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.*;

@Service
public class RetrofitCodeWriter {

    private static final Logger log = LoggerFactory.getLogger(RetrofitCodeWriter.class);

    @Autowired
    private JavaBeanCodeWriter javaBeanCodeWriter;

    @Autowired
    private EnumCodeWriter enumCodeWriter;

    @Autowired
    private ClasspathFreeMarker classpathFreeMarker;

    private Template interfaceTemplate = null;

    @PostConstruct
    public void init() {
        try {
            interfaceTemplate = classpathFreeMarker.getTemplate(getClass(), //
                    "retrofit.java.ftl");
            log.info("RetrofitCodeWriter inited done.");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void writeCode(List<ApiFolderObject> folders, CodeOutput out, CodeConfig config) {
        if (folders == null || folders.size() == 0) {
            return;
        }

        if (out == null) {
            throw new NullPointerException("CodeWriter writer is null.");
        }

        Set<Class<?>> enumClasses = new HashSet<>();
        KeyedList<String, ApiResultObject> javaBeans = new KeyedList<String, ApiResultObject>();
        for (ApiFolderObject folder : folders) {
            Map<String, Object> model = toModel(folder, config, javaBeans, enumClasses);
            String className = toRetrofitClassName(folder.getId());
            String fileName = className + ".java";
            try {
                String fileContent = classpathFreeMarker.build(interfaceTemplate, model);
                out.writeCodeFile(fileName, fileContent);
            } catch (IOException | TemplateException e) {
                throw new RuntimeException(e);
            }
        }

        Set<Class<?>> writtenClasses = new HashSet<>();
        List<ApiResultObject> results = javaBeans.getAll();
        for (ApiResultObject result : results) {
            Class<?> clazz = result.getSourceType();
            if (writtenClasses.contains(clazz)) {
                continue;
            }

            String className = clazz.getSimpleName();
            try {
                javaBeanCodeWriter.writeCode(result, className, out, config);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            writtenClasses.add(clazz);
        }

        for (Class<?> currentClass : enumClasses) {
            String className = currentClass.getSimpleName();
            try {
                enumCodeWriter.writeCode(currentClass, className, out, config);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }


    private String toRetrofitClassName(String id) {
        String name = id.substring(0, 1).toUpperCase(Locale.ENGLISH) + id.substring(1);
        if (name.endsWith("Controller")) {
            name = name.replaceAll("Controller", "Retrofit");
        } else {
            name += "Retrofit";
        }
        return name;
    }

    private Map<String, Object> toModel(ApiFolderObject folder, CodeConfig config, //
                                        KeyedList<String, ApiResultObject> javaBeans, Set<Class<?>> enumClasses) {

        Map<String, Object> model = new HashedMap<>();

        if (config == null) {
            config = new CodeConfig();
        }
        model.put("config", config);

        String className = toRetrofitClassName(folder.getId());
        model.put("class", className);

        String comment = folder.getComment().javadoc(0);
        if (StringUtils.hasText(comment)) {
            model.put("comment", comment);
        }

        Set<String> imports = new HashSet<>();
        model.put("imports", imports);

        List<MethodInfo> methods = new ArrayList<>();
        List<ApiDocObject> docs = folder.getDocs();
        if (docs != null) {
            for (ApiDocObject doc : docs) {
                MethodInfo method = toMethodInfo(doc, config, imports);
                methods.add(method);

                List<ApiResultObject> results = doc.getResults();
                if (results == null || results.size() == 0) {
                    continue;
                }

                for (ApiResultObject result : results) {
                    String groupId = result.getGroupId();
                    if (StringUtils.hasText(groupId)
                            && !javaBeans.containsKey(groupId)) {
                        javaBeans.add(groupId, result);
                    }

                    Class<?> clazz = result.getSourceType();
                    if (clazz != null && clazz.isEnum()) {
                        enumClasses.add(clazz);
                    }
                    List<ApiResultObject> children = result.getChildren();
                    if (children != null) {
                        for (ApiResultObject child : children) {
                            clazz = child.getSourceType();
                            if (clazz != null && clazz.isEnum()) {
                                enumClasses.add(clazz);
                            }
                        }
                    }
                }
            }
        }
        model.put("methods", methods);

        return model;
    }

    private MethodInfo toMethodInfo(ApiDocObject doc, CodeConfig config, Set<String> imports) {
        MethodInfo method = new MethodInfo();
        method.setName(doc.getId());

        String comment = doc.getComment().javadoc(1);
        method.setComment(comment);

        List<String> annos = new ArrayList<>();
        RequestMethod type = doc.getMethods()[0];
        if (type == RequestMethod.POST) {
            annos.add("@FormUrlEncoded");
        }
        String path = doc.getPaths()[0];
        if (!path.endsWith("/")) {
            path = path + "/";
        }
        String anno = "@" + type.name() + "(\"" + path + "\")";
        annos.add(anno);
        method.setAnnos(annos);

        List<ApiParamObject> srcParams = new ArrayList<>();
        List<ApiParamObject> extraPrams = config.getExtraPrams(doc);
        if (extraPrams != null) {
            srcParams.addAll(extraPrams);
        }
        if (doc.getParams() != null) {
            srcParams.addAll(doc.getParams());
        }

        List<ParamInfo> params = new ArrayList<>();
        for (int i = 0; i < srcParams.size(); i++) {
            ApiParamObject srcParam = srcParams.get(i);
            ParamInfo param = toParam(srcParam, doc, imports);
            if (i < srcParams.size() - 1) {
                param.setExpression(param.getExpression() + ", ");
            }
            params.add(param);
        }
        method.setParams(params);

        // 确定返回类型的描述。
        String returnClass = null;
        List<ApiResultObject> results = doc.getResults();
        if (results != null && results.size() > 0) {
            ApiResultObject result = results.get(0);
            ApiDataType dataType = result.getDataType();
            if (dataType != null) {
                if (dataType == ApiDataType.ARRAY) {
                    returnClass = "List<" + result.getSourceType().getSimpleName() + ">";
                } else {
                    returnClass = result.getSourceType().getSimpleName();
                }
            }
        }
        if (returnClass == null) {
            Class<?> returnType = doc.getSourceMethod().getReturnType();
            if (returnType != null && returnType != void.class) {
                returnClass = returnType.getSimpleName();
            }
        }
        method.setReturnClass(returnClass);

        return method;
    }

    private ParamInfo toParam(ApiParamObject srcParam, ApiDocObject doc, Set<String> imports) {
        ParamInfo param = new ParamInfo();

        String id = srcParam.getId();
        param.setId(id);

        String comment = srcParam.getComment().javadoc(1);
        param.setComment(comment);

        StringBuffer expression = new StringBuffer();

        RequestMethod requestMethod = doc.getMethods()[0];
        ApiParamLocation location = srcParam.getLocation();
        String annoName = toParamAnnoName(location, requestMethod);
        expression.append("@").append(annoName) //
                .append("(\"").append(id).append("\")");

        Class<?> paramClass = Classes.toWrapType(srcParam.getSourceType());
        CodeUtils.addImport(paramClass, imports);
        expression.append(" ").append(paramClass.getSimpleName());
        expression.append(" ").append(id);

        param.setExpression(expression.toString());

        return param;
    }

    private String toParamAnnoName(ApiParamLocation location, RequestMethod requestMethod) {
        if (location == ApiParamLocation.RequestHeader) {
            return "Header";
        } else if (location == ApiParamLocation.PathVariable) {
            return "Path";
        } else if (location == ApiParamLocation.RequestParam) {
            if (requestMethod == RequestMethod.POST) {
                return "Field";
            } else {
                return "Query";
            }
        } else if (location == ApiParamLocation.CookieValue) {
            return "Header";
        } else if (location == ApiParamLocation.RequestPart) {
            return "Part";
        } else {
            throw new RuntimeException("ApiParamLocation" +
                    " location unsupported: " + location);
        }
    }

    public static final class ParamInfo {

        private String id;

        private String comment;

        private String expression;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        public String getExpression() {
            return expression;
        }

        public void setExpression(String expression) {
            this.expression = expression;
        }

    }

    public static final class MethodInfo {

        private List<ParamInfo> params;

        private List<String> annos;

        private String comment;

        private String name;

        private String returnClass;

        public String getReturnClass() {
            return returnClass;
        }

        public void setReturnClass(String returnClass) {
            this.returnClass = returnClass;
        }

        public List<ParamInfo> getParams() {
            return params;
        }

        public void setParams(List<ParamInfo> params) {
            this.params = params;
        }

        public List<String> getAnnos() {
            return annos;
        }

        public void setAnnos(List<String> annos) {
            this.annos = annos;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }
}



================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/config/Api2DocConfiguration.java
================================================
package com.terran4j.commons.api2doc.config;

import com.terran4j.commons.api2doc.codewriter.RetrofitCodeWriter;
import com.terran4j.commons.api2doc.controller.Api2DocController;
import com.terran4j.commons.api2doc.impl.Api2DocCollector;
import com.terran4j.commons.api2doc.meta.ApiMetaService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 可以通过配置 terran4j.api2doc.enabled 来
 * 启用或禁用文档服务。
 */
@ConditionalOnExpression("${api2doc.enabled:true}")
@ComponentScan(basePackageClasses = {
        Api2DocController.class,
        Api2DocCollector.class,
        RetrofitCodeWriter.class,
        ApiMetaService.class
})
@Configuration
public class Api2DocConfiguration {

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/config/EnableApi2Doc.java
================================================
package com.terran4j.commons.api2doc.config;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(Api2DocConfiguration.class)
public @interface EnableApi2Doc {

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/Api2DocController.java
================================================
package com.terran4j.commons.api2doc.controller;

import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.impl.Api2DocProperties;
import com.terran4j.commons.api2doc.impl.Api2DocService;
import com.terran4j.commons.api2doc.impl.DocMenuBuilder;
import com.terran4j.commons.api2doc.impl.DocPageBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Map;

@Controller
@RequestMapping(value = "/api2doc")
public class Api2DocController {

    private static final Logger log = LoggerFactory.getLogger(Api2DocController.class);

    @Autowired
    private DocMenuBuilder docMenuBuilder;

    @Autowired
    private DocPageBuilder docPageBuilder;

    @Autowired
    private Api2DocService apiDocService;

    @Autowired
    private Api2DocProperties api2DocProperties;

    /**
     * http://localhost:8080/api2doc/home.html
     * 整个文档页面,包含顶部标题栏、左侧菜单栏、右侧用 iframe 嵌入的内容区。
     */
    @RequestMapping(value = "/home.html", method = RequestMethod.GET)
    public String home(@RequestParam(value = "p", required = false) String p,
                       Map<String, Object> model) throws Exception {

        String title = api2DocProperties.getApi2docTitle();
        if (StringUtils.isEmpty(title)) {
            String serviceName = api2DocProperties.getServiceName();
            if (StringUtils.hasText(serviceName)) {
                title = serviceName.trim() + "——接口文档";
            }
        }
        if (StringUtils.isEmpty(title)) {
            title = "Api2Doc 接口文档";
        }
        model.put("title", title);

        String icon = api2DocProperties.getApi2docIcon();
        if (StringUtils.hasText(icon)) {
            model.put("icon", icon);
        }

        List<MenuData> menus = docMenuBuilder.getMenuGroups();
        model.put("menus", menus);

        // 当前要显示的内容。
        String docPath = getDocPath(p);
        model.put("docPath", docPath);
        model.put("v", apiDocService.getComponentVersion());

        p = p == null ? "" : p;
        model.put("p", p);

        if (log.isInfoEnabled()) {
            log.info("request home.html, model:\n{}", model);
        }
        return "api2doc/home";
    }

    private String getDocPath(String p) {
        String docPath = null;
        if (StringUtils.hasText(p)) {
            String[] strs = p.split("-");
            if (strs.length >= 3) {
                String docType = strs[0];
                String docGroup = strs[1];
                String docId = strs[2];
                docPath = String.format("/api2doc/%s/%s/%s.html",
                        docType, docGroup, docId);
            }
        }

        if (docPath == null) {
            docPath = "/api2doc/welcome.html";
        }

        return apiDocService.addAppDocVersion(docPath);
    }

    /**
     * http://localhost:8080/api2doc/welcome.html
     * 文档首页内容。
     */
    @RequestMapping(value = "/welcome.html", method = RequestMethod.GET)
    public String welcome(Map<String, Object> model) throws Exception {
        String md = docPageBuilder.loadMdFromResource("welcome.md");
        return md2HtmlPage(md, null, model);
    }

    /**
     * http://localhost:8080/api2doc/overview.html
     */
    @RequestMapping(value = "/md/{folderId}/{docId}.html", method = RequestMethod.GET)
    public String md(@PathVariable("folderId") String folderId,
                     @PathVariable("docId") String docId,
                     Map<String, Object> model) throws Exception {
        String md = docPageBuilder.loadMdFromResource(folderId, docId);
        return md2HtmlPage(md, null, model);
    }

    @RequestMapping(value = "/api/{fid}/{id}.html", method = RequestMethod.GET)
    public String api2doc(
            @PathVariable("fid") String folderId, @PathVariable("id") String id,
            Map<String, Object> model) throws Exception {
        ApiDocObject doc = apiDocService.getDocObject(folderId, id);
        String md = docPageBuilder.doc2Md(doc);
        String title = doc.getName();
        return md2HtmlPage(md, title, model);
    }

    @RequestMapping(value = "/test/{fid}/{id}.html", method = RequestMethod.GET)
    public String api2test(
            @PathVariable("fid") String folderId, @PathVariable("id") String id,
            Map<String, Object> model) throws Exception {
        ApiDocObject doc = apiDocService.getDocObject(folderId, id);
        model.put("doc", doc);
        model.put("v", apiDocService.getComponentVersion());
//        String md = docPageBuilder.doc2Md(doc);
//        String title = doc.getName();
        return "api2doc/test";
    }

    public String md2HtmlPage(String md, String title,
                              Map<String, Object> model) throws Exception {
        if (title != null) {
            model.put("title", title);
        }
        String html = docPageBuilder.md2Html(md);
        model.put("content", html);

        model.put("v", apiDocService.getComponentVersion());

        return "api2doc/doc";
    }

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiEntry.java
================================================
package com.terran4j.commons.api2doc.controller;

public class ApiEntry {

    private String key;

    private String value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ApiEntry apiEntry = (ApiEntry) o;

        if (key != null ? !key.equals(apiEntry.key) : apiEntry.key != null) return false;
        return value != null ? value.equals(apiEntry.value) : apiEntry.value == null;
    }

    @Override
    public int hashCode() {
        int result = key != null ? key.hashCode() : 0;
        result = 31 * result + (value != null ? value.hashCode() : 0);
        return result;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiInfo.java
================================================
package com.terran4j.commons.api2doc.controller;

import java.util.Arrays;
import java.util.List;

public class ApiInfo {

    String[] methods;

    String defaultMethod;

    String url;

    List<ApiEntry> params;

    List<ApiEntry> headers;

    public String[] getMethods() {
        return methods;
    }

    public void setMethods(String[] methods) {
        this.methods = methods;
    }

    public String getDefaultMethod() {
        return defaultMethod;
    }

    public void setDefaultMethod(String defaultMethod) {
        this.defaultMethod = defaultMethod;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public List<ApiEntry> getParams() {
        return params;
    }

    public void setParams(List<ApiEntry> params) {
        this.params = params;
    }

    public List<ApiEntry> getHeaders() {
        return headers;
    }

    public void setHeaders(List<ApiEntry> headers) {
        this.headers = headers;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ApiInfo apiInfo = (ApiInfo) o;

        // Probably incorrect - comparing Object[] arrays with Arrays.equals
        if (!Arrays.equals(methods, apiInfo.methods)) return false;
        if (defaultMethod != null ? !defaultMethod.equals(apiInfo.defaultMethod) : apiInfo.defaultMethod != null)
            return false;
        if (url != null ? !url.equals(apiInfo.url) : apiInfo.url != null) return false;
        if (params != null ? !params.equals(apiInfo.params) : apiInfo.params != null) return false;
        return headers != null ? headers.equals(apiInfo.headers) : apiInfo.headers == null;
    }

    @Override
    public int hashCode() {
        int result = Arrays.hashCode(methods);
        result = 31 * result + (defaultMethod != null ? defaultMethod.hashCode() : 0);
        result = 31 * result + (url != null ? url.hashCode() : 0);
        result = 31 * result + (params != null ? params.hashCode() : 0);
        result = 31 * result + (headers != null ? headers.hashCode() : 0);
        return result;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiMetaController.java
================================================
package com.terran4j.commons.api2doc.controller;

import com.terran4j.commons.api2doc.meta.ApiMetaService;
import com.terran4j.commons.api2doc.meta.ClassMeta;
import com.terran4j.commons.restpack.RestPackController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@RestPackController
@RequestMapping(value = "/api2doc/meta")
public class ApiMetaController {

    @Autowired
    private ApiMetaService apiMetaService;

    @RequestMapping(value = "/classes", method = RequestMethod.GET)
    public List<ClassMeta> getClassMetaList() throws Exception {
        return apiMetaService.toClassMetaList();
    }

    @RequestMapping(value = "/apiInfo/{fid}/{id}", method = RequestMethod.GET)
    public ApiInfo getApiInfo(@PathVariable String fid, @PathVariable String id) throws Exception {
        return apiMetaService.toApiInfo(fid, id);
    }

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/MenuData.java
================================================
package com.terran4j.commons.api2doc.controller;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.util.Strings;

import java.util.List;

public class MenuData implements Comparable<MenuData>{

    private boolean folder;

    private int order = Api2Doc.DEFAULT_ORDER;

    private String id;

    private String index;

    private String name;

    private String url;

    private List<MenuData> children;

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public final boolean isFolder() {
        return folder;
    }

    public final void setFolder(boolean folder) {
        this.folder = folder;
    }

    public final String getId() {
        return id;
    }

    public final void setId(String id) {
        this.id = id;
    }

    public final String getIndex() {
        return index;
    }

    public final void setIndex(String index) {
        this.index = index;
    }

    public final String getName() {
        return name;
    }

    public final void setName(String name) {
        this.name = name;
    }

    public final List<MenuData> getChildren() {
        return children;
    }

    public final void setChildren(List<MenuData> children) {
        this.children = children;
    }

    public final String getUrl() {
        return url;
    }

    public final void setUrl(String url) {
        this.url = url;
    }

    public final String toString() {
        return Strings.toString(this);
    }

    @Override
    public int compareTo( MenuData other) {
        MenuData o1 = this;
        MenuData o2 = other;

        if (o1.getOrder() < o2.getOrder()) {
            return -1;
        }
        if (o1.getOrder() > o2.getOrder()) {
            return 1;
        }
        return 0;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDataType.java
================================================
package com.terran4j.commons.api2doc.domain;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
import com.terran4j.commons.util.Jsons;

/**
 * api的基本数据类型。
 *
 * @author jiangwei
 */
public enum ApiDataType {

    BOOLEAN("boolean") {
        @Override
        public String getDefault() {
            return "false";
        }

        @Override
        public Object parseValue(String text) {
            return Boolean.parseBoolean(text);
        }

        @Override
        public boolean isSimpleType() {
            return true;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    INT("int") {
        @Override
        public String getDefault() {
            return "0";
        }

        @Override
        public Object parseValue(String text) {
            return Integer.parseInt(text);
        }

        @Override
        public boolean isSimpleType() {
            return true;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    LONG("long") {
        @Override
        public String getDefault() {
            return "0";
        }

        @Override
        public Object parseValue(String text) {
            return Long.parseLong(text);
        }

        @Override
        public boolean isSimpleType() {
            return true;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    NUMBER("number") {
        @Override
        public String getDefault() {
            return "0.1";
        }

        @Override
        public Object parseValue(String text) {
            return Double.parseDouble(text);
        }

        @Override
        public boolean isSimpleType() {
            return true;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    STRING("string") {
        @Override
        public String getDefault() {
            return "my-string";
        }

        @Override
        public Object parseValue(String text) {
            return text;
        }

        @Override
        public boolean isSimpleType() {
            return true;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    ARRAY("array") {
        @Override
        public String getDefault() {
            return "[]";
        }

        @Override
        public Object parseValue(String text) {
            throw new UnsupportedOperationException("array can't parse from text: " + text);
        }

        @Override
        public boolean isSimpleType() {
            return false;
        }

        @Override
        public boolean isArrayType() {
            return true;
        }

        @Override
        public boolean isObjectType() {
            return false;
        }
    },

    OBJECT("object") {
        @Override
        public String getDefault() {
            return "{}";
        }

        @Override
        public Object parseValue(String text) {
            throw new UnsupportedOperationException("object can't parse from text: " + text);
        }

        @Override
        public boolean isSimpleType() {
            return false;
        }

        @Override
        public boolean isArrayType() {
            return false;
        }

        @Override
        public boolean isObjectType() {
            return true;
        }
    };

    private final String name;

    ApiDataType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract String getDefault();

    public abstract Object parseValue(String text);

    public abstract boolean isSimpleType();

    public abstract boolean isArrayType();

    public abstract boolean isObjectType();

    private static JsonSchemaGenerator schemaGen = null;

    public static final JsonSchemaGenerator getJsonSchemaGenerator() {
        if (schemaGen != null) {
            return schemaGen;
        }
        synchronized (ApiDataType.class) {
            if (schemaGen != null) {
                return schemaGen;
            }
            try {
                schemaGen = new JsonSchemaGenerator(Jsons.getObjectMapper());
                return schemaGen;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static ApiDataType toDataType(Class<?> clazz) {

        // 日期类型,按 long 返回。
        ApiDataType dataType = DateConverter.dateAsLongType(clazz);
        if (dataType != null) {
            return dataType;
        }

        try {
            JsonSchema schema = getJsonSchemaGenerator().generateSchema(clazz);
            return toDataType(schema);
        } catch (JsonMappingException e) {
            String msg = "generate schema by class failed, class = " + clazz.getName();
            throw new RuntimeException(msg, e);
        }
    }

    public static ApiDataType toDataType(JsonSchema schema) {
        if (schema == null) {
            return null;
        }
        if (schema.isBooleanSchema()) {
            return ApiDataType.BOOLEAN;
        }
        if (schema.isIntegerSchema()) {
            return ApiDataType.INT;
        }
        if (schema.isStringSchema()) {
            return ApiDataType.STRING;
        }
        if (schema.isNumberSchema()) {
            return ApiDataType.NUMBER;
        }
        if (schema.isObjectSchema()) {
            return ApiDataType.OBJECT;
        }
        if (schema.isArraySchema()) {
            return ApiDataType.ARRAY;
        }
        return null;
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocObject.java
================================================
package com.terran4j.commons.api2doc.domain;

import com.terran4j.commons.api2doc.impl.Api2DocObjectFactory;
import com.terran4j.commons.util.value.KeyedList;
import org.springframework.web.bind.annotation.RequestMethod;

import java.lang.reflect.Method;
import java.util.List;

public class ApiDocObject extends ApiObject {

    private ApiFolderObject folder;

    private String[] paths;

    private Method sourceMethod;

    private RequestMethod[] methods;

    private String returnTypeDesc;

    private List<ApiResultObject> results;

    private ApiResultObject resultType;

    private final KeyedList<String, ApiParamObject> params = new KeyedList<>();

    private final KeyedList<String, ApiErrorObject> errors = new KeyedList<>();

    public ApiResultObject getResultType() {
        return resultType;
    }

    public void setResultType(ApiResultObject resultType) {
        this.resultType = resultType;
    }

    public Method getSourceMethod() {
        return sourceMethod;
    }

    public void setSourceMethod(Method sourceMethod) {
        this.sourceMethod = sourceMethod;
    }

    public String[] getPaths() {
        return paths;
    }

    public void setPaths(String[] paths) {
        this.paths = paths;
    }

    public RequestMethod[] getMethods() {
        return methods;
    }

    public void setMethods(RequestMethod[] methods) {
        this.methods = methods;
    }

    public final List<ApiParamObject> getParams() {
        return params.getAll();
    }

    public final ApiParamObject getParam(String id) {
        return params.get(id);
    }

    public final void addParam(ApiParamObject param) {
        this.params.add(param.getId(), param);
    }

    public List<ApiResultObject> getResults() {
        return results;
    }

    public void setResults(List<ApiResultObject> results) {
        this.results = results;
    }

    public List<ApiErrorObject> getErrors() {
        return errors.getAll();
    }

    public void addError(ApiErrorObject error) {
        this.errors.add(error.getId(), error);
    }

    public ApiFolderObject getFolder() {
        return folder;
    }

    public void setFolder(ApiFolderObject folder) {
        this.folder = folder;
    }

    public String getReturnTypeDesc() {
        return returnTypeDesc;
    }

    public void setReturnTypeDesc(String returnTypeDesc) {
        this.returnTypeDesc = returnTypeDesc;
    }

    public final Object toMockResult() {
        List<ApiResultObject> results = getResults();
        if (results != null && results.size() > 0) {
            ApiResultObject result = results.get(0);
            return Api2DocObjectFactory.createObject(result.getDataType(),
                    result.getSourceType(), result.getSample().getValue());
        }
        if (resultType != null) {
            return Api2DocObjectFactory.createObject(resultType.getDataType(),
                    resultType.getSourceType(), resultType.getSample().getValue());
        }
        return null;
    }
}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocUtils.java
================================================
package com.terran4j.commons.api2doc.domain;

import org.springframework.util.StringUtils;

import com.terran4j.commons.api2doc.annotations.Api2Doc;

public class ApiDocUtils {

	public static final String getId(Class<?> clazz) {
		if (clazz == null) {
			throw new NullPointerException();
		}

		Api2Doc api2doc = clazz.getAnnotation(Api2Doc.class);

		if (api2doc != null) {
			String id = api2doc.id();
			if (StringUtils.hasText(id)) {
				return id;
			}

			String value = api2doc.value();
			if (StringUtils.hasText(value)) {
				return value;
			}
		}

		return clazz.getName();
	}
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiErrorObject.java
================================================
package com.terran4j.commons.api2doc.domain;

public class ApiErrorObject extends ApiObject {

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiFolderObject.java
================================================
package com.terran4j.commons.api2doc.domain;

import com.terran4j.commons.util.value.KeyedList;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

public class ApiFolderObject extends ApiObject {

    private boolean restPack = false;

    private Map<String, String> mds;

    private Class<?> sourceClass;

    private final KeyedList<String, ApiDocObject> docs = new KeyedList<>();

    public boolean isRestPack() {
        return restPack;
    }

    public void setRestPack(boolean restPack) {
        this.restPack = restPack;
    }

    public Map<String, String> getMds() {
        return mds;
    }

    public void setMds(Map<String, String> mds) {
        this.mds = mds;
    }

    public Class<?> getSourceClass() {
        return sourceClass;
    }

    public void setSourceClass(Class<?> sourceClass) {
        this.sourceClass = sourceClass;
    }

    public final List<ApiDocObject> getDocs() {
        return docs.getAll();
    }

    public final ApiDocObject getDoc(String id) {
        return docs.get(id);
    }

    public final void addDocs(List<ApiDocObject> docList) {
        if (docList == null) {
            return;
        }
        for (ApiDocObject doc : docList) {
            addDoc(doc);
        }
    }

    public final void addDoc(ApiDocObject doc) {
        if (doc == null) {
            throw new NullPointerException();
        }
        String id = doc.getId();
        if (StringUtils.isEmpty(id)) {
            throw new NullPointerException("doc id is empty.");
        }

        this.docs.add(id, doc);
    }

    public static final String name2Id(String name) {
        int hash = name.hashCode();
        String id;
        if (hash < 0) {
            id = "n" + Math.abs(hash);
        } else {
            id = String.valueOf(hash);
        }
        return id;
    }

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiObject.java
================================================
package com.terran4j.commons.api2doc.domain;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.impl.FlexibleString;
import com.terran4j.commons.util.Strings;

public class ApiObject implements Comparable<ApiObject>{

    private String id;

    private String name;

    private final FlexibleString comment = new FlexibleString();

    private final FlexibleString sample = new FlexibleString();

    private int order = Api2Doc.DEFAULT_ORDER;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public final int getOrder() {
        return order;
    }

    public final void setOrder(int order) {
        this.order = order;
    }

    public void insertComment(String comment) {
        this.comment.insertLine(comment);
    }

    public FlexibleString getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment.setValue(comment);
    }

    public FlexibleString getSample() {
        return sample;
    }

    public void setSample(String sample) {
        this.sample.setValue(sample);
    }

    @Override
    public final String toString() {
        return Strings.toString(this);
    }

    @Override
    public int compareTo(ApiObject other) {
        ApiObject o1 = this;
        ApiObject o2 = other;

        // 优先按用户指定排序。
        if (o1.getOrder() < o2.getOrder()) {
            return -1;
        }
        if (o1.getOrder() > o2.getOrder()) {
            return 1;
        }

        // 其次按 id 字符串排序。
        return o1.getId().compareTo(o2.getId());
    }
}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamLocation.java
================================================
package com.terran4j.commons.api2doc.domain;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.AnnotatedElement;

/**
 * API 参数在 HTTP 协议中的位置。
 *
 * @author jiangwei
 */
public enum ApiParamLocation {

    RequestHeader {
        @Override
        boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement element) {
            RequestHeader requestHeader = element.getAnnotation(RequestHeader.class);
            if (requestHeader == null) {
                return false;
            }

            String name = null;
            if (StringUtils.hasText(requestHeader.value())) {
                name = requestHeader.value();
            }
            if (StringUtils.hasText(requestHeader.name())) {
                name = requestHeader.name();
            }
            apiParamObject.setName(name);

            boolean required = requestHeader.required();
            apiParamObject.setRequired(required);

            String paramSample = requestHeader.defaultValue();
            if (StringUtils.hasText(paramSample)) {
                if (ValueConstants.DEFAULT_NONE.equals(paramSample)) {
                    paramSample = "";
                }
                apiParamObject.setSample(paramSample);
            }

            return true;
        }
    },

    RequestParam {
        @Override
        boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement element) {
            RequestParam requestParam = element.getAnnotation(RequestParam.class);
            if (requestParam == null) {
                return false;
            }

            String name = null;
            if (StringUtils.hasText(requestParam.value())) {
                name = requestParam.value();
            }
            if (StringUtils.hasText(requestParam.name())) {
                name = requestParam.name();
            }
            apiParamObject.setName(name);

            boolean required = requestParam.required();
            apiParamObject.setRequired(required);

            String paramSample = requestParam.defaultValue();
            if (StringUtils.hasText(paramSample)) {
                if (ValueConstants.DEFAULT_NONE.equals(paramSample)) {
                    paramSample = "";
                }
                apiParamObject.setSample(paramSample);
            }

            return true;
        }
    },

    RequestPart {
        @Override
        boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement element) {
            RequestPart requestPart = element.getAnnotation(RequestPart.class);
            if (requestPart == null) {
                return false;
            }

            String name = null;
            if (StringUtils.hasText(requestPart.value())) {
                name = requestPart.value();
            }
            if (StringUtils.hasText(requestPart.name())) {
                name = requestPart.name();
            }
            apiParamObject.setName(name);

            boolean required = requestPart.required();
            apiParamObject.setRequired(required);

            return true;
        }
    },

    CookieValue {
        @Override
        boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement element) {
            CookieValue cookieValue = element.getAnnotation(CookieValue.class);
            if (cookieValue == null) {
                return false;
            }

            String name = null;
            if (StringUtils.hasText(cookieValue.value())) {
                name = cookieValue.value();
            }
            if (StringUtils.hasText(cookieValue.name())) {
                name = cookieValue.name();
            }
            apiParamObject.setName(name);

            boolean required = cookieValue.required();
            apiParamObject.setRequired(required);

            String paramSample = cookieValue.defaultValue();
            if (StringUtils.hasText(paramSample)) {
                if (ValueConstants.DEFAULT_NONE.equals(paramSample)) {
                    paramSample = "";
                }
                apiParamObject.setSample(paramSample);
            }

            return true;
        }
    },

    PathVariable {
        @Override
        boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement element) {
            PathVariable pathVariable = element.getAnnotation(PathVariable.class);
            if (pathVariable == null) {
                return false;
            }

            String name = null;
            if (StringUtils.hasText(pathVariable.value())) {
                name = pathVariable.value();
            }
            if (StringUtils.hasText(pathVariable.name())) {
                name = pathVariable.name();
            }
            apiParamObject.setName(name);

            boolean required = pathVariable.required();
            apiParamObject.setRequired(required);

            return true;
        }
    };

    public static final ApiParamLocation[] API_PARAM_LOCATIONS = new ApiParamLocation[]{
            RequestParam, PathVariable, RequestHeader, CookieValue, RequestPart
    };

    abstract boolean doCollect(ApiParamObject apiParamObject, AnnotatedElement param);

    public static final void collects(ApiParamObject apiParamObject, AnnotatedElement element) {
        ApiParamLocation currentLocation = ApiParamLocation.RequestParam;
        for (ApiParamLocation location : API_PARAM_LOCATIONS) {
            if (location.doCollect(apiParamObject, element)) {
                currentLocation = location;
                break;
            }
        }
        apiParamObject.setLocation(currentLocation);

        String sample = apiParamObject.getSample().getValue();
        if (ValueConstants.DEFAULT_NONE.equals(sample)) {
            apiParamObject.setSample("");
        }
    }

}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamObject.java
================================================
package com.terran4j.commons.api2doc.domain;

public class ApiParamObject extends ApiObject {
	
	private boolean required;

	private ApiDataType dataType;
	
	private ApiParamLocation location;
	
	private Class<?> sourceType;
	
	public ApiParamObject() {
		super();
		this.setComment("");
	}
	
	public Class<?> getSourceType() {
		return sourceType;
	}

	public void setSourceType(Class<?> sourceType) {
		this.sourceType = sourceType;
	}

	public String getTypeName() {
		if (dataType == null) {
			return "";
		}
		if (dataType.isArrayType()) {
			return dataType.name().toLowerCase() + "[]";
		}
		return dataType.name().toLowerCase();
	}

	public ApiDataType getDataType() {
		return dataType;
	}

	public void setDataType(ApiDataType type) {
		this.dataType = type;
	}

	public boolean isRequired() {
		return required;
	}

	public void setRequired(boolean required) {
		this.required = required;
	}
	
	public final String getRequiredName() {
		return required ? "是" : "否";
	}

	public ApiParamLocation getLocation() {
		return location;
	}

	public void setLocation(ApiParamLocation location) {
		this.location = location;
	}
	
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiResultObject.java
================================================
package com.terran4j.commons.api2doc.domain;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.impl.Api2DocUtils;
import com.terran4j.commons.api2doc.impl.ApiCommentUtils;
import com.terran4j.commons.util.Classes;
import com.terran4j.commons.util.value.KeyedList;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 记录所有的结果字段,它是一个复合型
 */
public class ApiResultObject extends ApiObject {

    private static final Logger log = LoggerFactory.getLogger(ApiResultObject.class);

    private ApiDataType dataType;

    /**
     * 如果类型是数组类型,此类是里面元素的类型
     * 否则是这个类型本身。
     */
    private Class<?> sourceType;

    private String typeName = "";

    private String refGroupId = null;

    private String groupId = null;

    private String groupName = null;

    private final List<ApiResultObject> children = new ArrayList<>();

    public Class<?> getSourceType() {
        return sourceType;
    }

    public void setSourceType(Class<?> sourceType) {
        this.sourceType = sourceType;
    }

    public String getRefGroupId() {
        return refGroupId;
    }

    public void setRefGroupId(String refGroupId) {
        this.refGroupId = refGroupId;
    }

    public final ApiDataType getDataType() {
        return dataType;
    }

    public final void setDataType(ApiDataType dataType) {
        this.dataType = dataType;
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public final List<ApiResultObject> getChildren() {
        return children;
    }

    public final ApiResultObject getChild(String fieldName) {
        if (children == null || StringUtils.isEmpty(fieldName)) {
            return null;
        }

        for (ApiResultObject child : children) {
            if (fieldName.equals(child.getId())) {
                return child;
            }
        }

        return null;
    }

    public final void addChild(ApiResultObject child) {
        this.children.add(child);
    }

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static final String getEnumComment(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        if (!clazz.isEnum()) {
            return null;
        }

        StringBuffer sb = new StringBuffer("\n可选值为:");
        Class<Enum<?>> enumClass = (Class<Enum<?>>) clazz;
        Enum[] enums = enumClass.getEnumConstants();
        for (Enum e : enums) {
            String name = e.name();
            Field field = null;
            try {
                field = enumClass.getDeclaredField(name);
            } catch (NoSuchFieldException | SecurityException e1) {
                log.error("Can't get field \"" + name + "\" from Enum: " + clazz.getName(), e1);
                continue;
            }
            ApiComment comment = field.getAnnotation(ApiComment.class);
            String value = ApiCommentUtils.getComment(
                    comment, null, field.getName());
            if (value == null) {
                value = "";
            }

            if (sb.length() > 0) {
                sb.append("\n");
            }
            sb.append(name).append(": ").append(value).append("; ");
        }

        return sb.toString();
    }

    private static final String getTypeName(Class<?> clazz, ApiDataType dataType) {
        if (clazz.isEnum()) {
            return ApiDataType.STRING.name().toLowerCase() + "(枚举值)";
        } else if (dataType != null && dataType.isSimpleType()) {
            return dataType.name().toLowerCase();
        } else {
            return clazz.getSimpleName();
        }
    }

    /**
     * 找到一个方法返回类型中字段,收集它的 Api2Doc 信息。
     *
     * @param method
     * @param totalResults
     * @return
     */
    public static final ApiResultObject parseResultType(
            Method method, KeyedList<String, ApiResultObject> totalResults) {

        if (method == null) {
            return null;
        }

        if (totalResults == null) {
            totalResults = new KeyedList<>();
        }

        final Class<?> clazz = method.getReturnType();
        final ApiDataType dataType = ApiDataType.toDataType(clazz);
        if (dataType == null) {
            return null;
        }
        String typeName = getTypeName(clazz, dataType);

        // 基本类型,直接处理。
        if (dataType.isSimpleType()) {
            return createSimple(clazz, clazz, dataType, typeName);
        }

        // 子类型。
        Class<?> elementType = null;

        // 数组类型,找到它的元素的具体类型,然后处理具体类型。
        if (dataType.isArrayType()) {
            elementType = Api2DocUtils.getArrayElementClass(method);
            if (elementType == null) {
                log.warn("Can't find element class by method: {}", method);
                return null;
            }

            ApiDataType elementDataType = ApiDataType.toDataType(elementType);
            typeName = getTypeName(elementType, elementDataType) + "[]";

            // 数组类型,但元素是基本类型的,也直接处理。
            if (elementDataType != null && elementDataType.isSimpleType()) {
                return createSimple(elementType, clazz,
                        dataType, typeName);
            }
        }

        // 复杂类型的情况。
        ApiResultObject result = new ApiResultObject();
        result.setDataType(dataType);
        result.setSourceType(clazz);
        result.setTypeName(typeName);
        result.setId("");

        if (dataType.isObjectType()) {
            elementType = method.getReturnType();
        }

        // 没有子类型,直接返回。
        // TODO:  暂时不解析 Map 内部的类型。
        if (elementType == null || Map.class.equals(elementType)) {
            return result;
        }

        result.setSourceType(elementType);

        // 没有子类型,直接返回。
        PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(elementType);
        if (props == null || props.length == 0) {
            return result;
        }

        // 根据类型生成字段集的 id 和 name 。
        String groupId = getGroupId(elementType);
        result.setGroupId(groupId);
        String groupName = elementType.getSimpleName();
        result.setGroupName(groupName);

        // 加入到结果字段集中。
        if (totalResults.containsKey(groupId)) {
            return result;
        } else {
            totalResults.add(groupId, result);
        }

        // 有子类型,补充子类型信息。
        for (PropertyDescriptor prop : props) {
            if (Api2DocUtils.isFilter(prop, elementType)) {
                continue;
            }

            String fieldName = prop.getName();
            Method subMethod = prop.getReadMethod();

            // 处理子类型。
            ApiResultObject childPropResult;
            try {
                childPropResult = parseResultType(subMethod, totalResults);
            } catch (Exception e) {
                String msg = String.format("解析类[ %s ]的属性[ %s ]出错: %s",
                        elementType.getName(), fieldName, e.getMessage());
                throw new RuntimeException(msg);
            }

            // 补充子类型信息。
            if (childPropResult != null) {

                // 补充到当前节点中。
                result.addChild(childPropResult);

                String id = prop.getName();
                childPropResult.setId(id);
                childPropResult.setName(id);

                Class<?> childPropClass = subMethod.getReturnType();
                ApiDataType childPropDataType = ApiDataType.toDataType(childPropClass);
                childPropResult.setDataType(childPropDataType);

                Api2Doc childApi2Doc;
                ApiComment childApiComment;
                String childName;
                Field field = Classes.getField(id, elementType);
                if (field != null) {
                    childApiComment = field.getAnnotation(ApiComment.class);
                    childApi2Doc = field.getAnnotation(Api2Doc.class);
                    childName = field.getName();
                } else {
                    childApiComment = subMethod.getAnnotation(ApiComment.class);
                    childApi2Doc = subMethod.getAnnotation(Api2Doc.class);
                    childName = subMethod.getName();
                }

                ApiComment elementApiComment = elementType
                        .getAnnotation(ApiComment.class);
                Class<?> defaultSeeClass = ApiCommentUtils
                        .getDefaultSeeClass(elementApiComment, null);

                String comment = ApiCommentUtils.getComment(
                        childApiComment, defaultSeeClass, childName);
                if (comment == null) {
                    comment = "";
                }
                childPropResult.insertComment(comment);

                String sample = ApiCommentUtils.getSample(
                        childApiComment, defaultSeeClass, childName);
                if (sample == null) {
                    sample = "";
                }
                childPropResult.setSample(sample);

                if (childApi2Doc != null) {
                    childPropResult.setOrder(childApi2Doc.order());
                }

                // 记录所引用的类型。
                Class<?> childSubType = null;
                if (childPropDataType != null) {
                    if (childPropDataType.isArrayType()) {
                        childSubType = Api2DocUtils.getArrayElementClass(subMethod);
                    } else if (childPropDataType.isObjectType()) {
                        childSubType = subMethod.getReturnType();
                    }
                }
                if (childSubType != null) {
                    String refGroupId = getGroupId(childSubType);
                    childPropResult.setRefGroupId(refGroupId);
                }
            }
        }

        Collections.sort(result.getChildren());

        return result;
    }

    public static final String getGroupId(Class<?> clazz) {
        if (clazz == null) {
            throw new NullPointerException();
        }
        String groupId = ApiDocUtils.getId(clazz);
        return groupId;
    }

    private static ApiResultObject createSimple(Class<?> sourceType,
                                                Class<?> clazz, ApiDataType dataType,
                                                String typeName) {
        ApiResultObject result = new ApiResultObject();
        result.setSourceType(sourceType);
        result.setDataType(dataType);
        result.setTypeName(typeName);
        result.insertComment(getEnumComment(clazz));
        result.setId("");
        return result;
    }


}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/DateConverter.java
================================================
package com.terran4j.commons.api2doc.domain;

import java.util.Date;

public class DateConverter {

    public static boolean isDateType(Class<?> clazz) {
        return clazz == Date.class || clazz == java.sql.Date.class;
    }

    public static Object dateAsLongValue(Class<?> clazz) {
        if (isDateType(clazz)) {
            // 这里不能用 Long 类型,因为赋值会失败。
            return new Date();
        }
        return null;
    }

    public static ApiDataType dateAsLongType(Class<?> clazz) {
        if (isDateType(clazz)) {
            return ApiDataType.LONG;
        }
        return null;
    }

    public static Class<?> dateAsLongClass(Class<?> clazz) {
        if (isDateType(clazz)) {
            return Long.class;
        }
        return clazz;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocCollector.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.annotations.Api2Doc;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.annotations.ApiError;
import com.terran4j.commons.api2doc.annotations.ApiErrors;
import com.terran4j.commons.api2doc.domain.*;
import com.terran4j.commons.restpack.RestPackController;
import com.terran4j.commons.util.Classes;
import com.terran4j.commons.util.error.BusinessException;
import com.terran4j.commons.util.value.KeyedList;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;


@Service
public class Api2DocCollector implements BeanPostProcessor {

    private static final Logger log = LoggerFactory.getLogger(Api2DocCollector.class);

    private final LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer
            = new LocalVariableTableParameterNameDiscoverer();

    @Autowired
    private Api2DocService apiDocService;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        ApiFolderObject folder;
        try {
            folder = toApiFolder(bean, beanName);
        } catch (BusinessException e) {
            throw new BeanDefinitionStoreException(
                    "bean上的文档信息定义出错:" + e.getMessage());
        }
        if (folder == null) {
            return bean;
        }

        String id = folder.getId();
        ApiFolderObject existApiFolder = apiDocService.getFolder(id);
        if (existApiFolder != null) {
            String msg = "@Api2Doc id值重复: " + id;
            throw new BeanDefinitionStoreException(msg);
        }

        if (folder != null) {
            apiDocService.addFolder(folder);
        }
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 解析 API 组,一组 API 对应一个 Controller 类, 其中每个 method 对应一个 api 。<br>
     * 只要有 @ApiDoc 注解,有会生成文档,没有这个注解就不会。
     *
     * @param bean
     * @param beanName
     * @return
     */
    public ApiFolderObject toApiFolder(Object bean, String beanName) throws BusinessException {

        Class<?> clazz = Classes.getTargetClass(bean);
        Controller controller = AnnotationUtils.findAnnotation(clazz, Controller.class);
        if (controller == null) {
            // 不是 Controller 类,不用收集。
            return null;
        }
        if (log.isInfoEnabled()) {
            log.info("prepare to get API Info by bean:  {}", beanName);
        }

        List<MappingMethod> methods = MappingMethod.getMappingMethods(clazz);
        // Classes.getMethods(RequestMapping.class, clazz);
        if (methods == null || methods.size() == 0) {
            // 整个类中都没有任何 RequestMapping 的方法,不用收集。
//            if (log.isInfoEnabled()) {
//                log.info("No any @RequestMapping /  method, no need to get, " +
//                        "beanName = {}", beanName);
//            }
            return null;
        }

        Api2Doc classApi2Doc = clazz.getAnnotation(Api2Doc.class);
        if (classApi2Doc != null && classApi2Doc.ignore()) {
            // 整个类的文档被忽略。
            if (log.isInfoEnabled()) {
                log.info("@Api2Doc ignore = true, no need to get, " +
                        "beanName = {}", beanName);
            }
            return null;
        }

        List<MappingMethod> ali2DocMethods = new ArrayList<>();
        for (MappingMethod mappingMethod : methods) {
            Method method = mappingMethod.getMethod();
            Api2Doc api2Doc = method.getAnnotation(Api2Doc.class);
            if (classApi2Doc == null && api2Doc == null) {
                // 本方法的文档被忽略。
                continue;
            }
            if (api2Doc != null && api2Doc.ignore()) {
                // 本方法的文档被忽略。
                continue;
            }
            ali2DocMethods.add(mappingMethod);
        }
        if (classApi2Doc == null && ali2DocMethods.size() == 0) {
            // 整个类中的方法,都忽略从 API 生成文档,不用收集。
            if (log.isInfoEnabled()) {
                log.info("all method were ignored, no need to get, beanName = {}", beanName);
            }
            return null;
        }

        ApiFolderObject folder = new ApiFolderObject();

        folder.setSourceClass(clazz);

        String id = beanName;
        if (classApi2Doc != null && StringUtils.hasText(classApi2Doc.value())) {
            id = classApi2Doc.value();
        }
        if (classApi2Doc != null && StringUtils.hasText(classApi2Doc.id())) {
            id = classApi2Doc.id();
        }
        folder.setId(id);
        checkId(id);

        String pathPattern = "api2doc/" + id + "/*.md";
        try {
            Resource[] resources = Classes.scanResources(pathPattern);
            if (resources != null && resources.length > 0) {
                Map<String, String> mds = new HashMap<>();
                for (Resource resource : resources) {
                    String md = resource.getFilename();
                    mds.put(ApiFolderObject.name2Id(md), md);
                }
                folder.setMds(mds);
            }
        } catch (IOException e) {
            String msg = "scan classpath[" + pathPattern + "] failed: " + e.getMessage();
            throw new BeanDefinitionStoreException(msg);
        }

        if (classApi2Doc != null) {
            folder.setOrder(classApi2Doc.order());
        }

        // API 组的名称。
        String name = beanName;
        RequestMapping classMapping = clazz.getAnnotation(RequestMapping.class);
        if (classMapping != null && StringUtils.hasText(classMapping.name())) {
            name = classMapping.name();
        }
        if (classApi2Doc != null && StringUtils.hasText(classApi2Doc.name())) {
            name = classApi2Doc.name();
        }
        folder.setName(name);

        // 这组 API 是否用了 RestPack
        RestPackController restPackController = clazz.getAnnotation(RestPackController.class);
        folder.setRestPack(restPackController != null);

        // API 组的注释。
        ApiComment apiComment = clazz.getAnnotation(ApiComment.class);
        folder.setComment(ApiCommentUtils.getComment(
                apiComment, null, null));

        // 在类上的 seeClass ,是默认的。
        Class<?> defaultSeeClass = ApiCommentUtils.getDefaultSeeClass(
                apiComment, null);

        // API 组的路径前缀。
        String[] basePaths = getPath(classMapping);

        // 根据方法生成 API 文档。
        List<ApiDocObject> docs = new ArrayList<>();
        for (MappingMethod method : ali2DocMethods) {
            ApiDocObject doc = getApiDoc(method, basePaths, beanName,
                    classApi2Doc, defaultSeeClass);
            if (doc == null) {
                continue;
            }

            String docId = doc.getId();
            ApiDocObject existDoc = folder.getDoc(docId);
            if (existDoc != null) {
                String msg = "文档id值重复: " + docId + "\n"
                        + "如果方法上没有用  @Api2Doc(id = \"xxx\") 来指定文档id,则重载方法会出现此问题。\n"
                        + "请在重载的方法上用 @Api2Doc(id = \"xxx\") 来指定一个不同的文档id";
                throw new BeanDefinitionStoreException(msg);
            }

            doc.setFolder(folder);
            docs.add(doc);
            if (log.isInfoEnabled()) {
                log.info("add doc: {}/{}", folder.getId(), docId);
            }
        }
        Collections.sort(docs);
        folder.addDocs(docs);

        return folder;
    }

    ApiDocObject getApiDoc(
            MappingMethod mappingMethod, String[] basePaths,
            String beanName, Api2Doc classApi2Doc,
            Class<?> defaultSeeClass) throws BusinessException {

        Method method = mappingMethod.getMethod();

        // 只要有 @ApiDoc 注解(无论是本方法上,还是类上),有会生成文档,没有这个注解就不会。
        Api2Doc api2Doc = method.getAnnotation(Api2Doc.class);
        if (api2Doc == null && classApi2Doc == null) {
            return null;
        }

        ApiDocObject doc = new ApiDocObject();

        doc.setSourceMethod(method);

        // 获取文档的 id,以 @Api2Doc、方法名 为顺序获取。
        String id = method.getName();
        if (api2Doc != null && StringUtils.hasText(api2Doc.value())) {
            id = api2Doc.value();
        }
        if (api2Doc != null && StringUtils.hasText(api2Doc.id())) {
            id = api2Doc.id();
        }
        doc.setId(id);
        checkId(id);

        // 获取文档的排序。
        if (api2Doc != null) {
            doc.setOrder(api2Doc.order());
        }

        // 获取文档名称,按 @Api2Doc 、@Mapping、方法名的顺序获取。
        String name = method.getName();
        String mappingName = mappingMethod.getName();
        if (StringUtils.hasText(mappingName)) {
            name = mappingName;
        }
        if (api2Doc != null && StringUtils.hasText(api2Doc.name())) {
            name = api2Doc.name();
        }
        doc.setName(name);

        // 获取 API 的注释信息。
        ApiComment apiComment = method.getAnnotation(ApiComment.class);
        defaultSeeClass = ApiCommentUtils.getDefaultSeeClass(apiComment, defaultSeeClass);
        String docComment = ApiCommentUtils.getComment(apiComment, defaultSeeClass, name);
        doc.setComment(docComment);
        String docSample = ApiCommentUtils.getSample(apiComment, defaultSeeClass, name);
        doc.setSample(docSample);

        // 获取 API 的访问路径。
        String[] paths = mappingMethod.getPath();
        paths = combine(basePaths, paths);
        doc.setPaths(paths);

        // 获取 HTTP 方法。
        doc.setMethods(mappingMethod.getRequestMethod());

        // 收集参数信息。
        List<ApiParamObject> apiParams = toApiParams(method, defaultSeeClass);
        if (apiParams != null && apiParams.size() > 0) {
            for (ApiParamObject apiParam : apiParams) {
                doc.addParam(apiParam);
            }
        }

        // 收集返回值信息。
        KeyedList<String, ApiResultObject> totalResults = new KeyedList<>();
        ApiResultObject resultObject = ApiResultObject.parseResultType(method, totalResults);
        if (resultObject != null) {
            resultObject.setComment(docComment);
            resultObject.setSample(docSample);
        }
        doc.setResultType(resultObject);
        doc.setResults(totalResults.getAll());


        // 确定返回类型的描述。
        String returnTypeDesc = null;
        List<ApiResultObject> results = doc.getResults();
        if (results != null && results.size() > 0) {
            ApiResultObject result = results.get(0);
            ApiDataType dataType = result.getDataType();
            if (dataType != null) {
                if (dataType == ApiDataType.ARRAY) {
                    returnTypeDesc = result.getSourceType().getSimpleName() + "[]";
                } else {
                    returnTypeDesc = result.getSourceType().getSimpleName();
                }
            }
        }
        if (returnTypeDesc == null) {
            Class<?> returnType = doc.getSourceMethod().getReturnType();
            if (returnType != null && returnType != void.class) {
                returnTypeDesc = returnType.getSimpleName();
            }
        }
        doc.setReturnTypeDesc(returnTypeDesc);

        // 收集错误码信息。
        ApiErrors errorCodes = method.getAnnotation(ApiErrors.class);
        if (errorCodes != null && errorCodes.value() != null
                && errorCodes.value().length > 0) {
            for (ApiError errorCode : errorCodes.value()) {
                ApiErrorObject error = getError(errorCode);
                if (error == null) {
                    continue;
                }
                doc.addError(error);
            }
        } else {
            ApiError errorCode = method.getAnnotation(ApiError.class);
            ApiErrorObject error = getError(errorCode);
            if (error != null) {
                doc.addError(error);
            }
        }

        return doc;
    }


    public List<ApiParamObject> toApiParams(Method method, Class<?> defaultSeeClass) {
        List<ApiParamObject> result = new ArrayList<>();
        Set<String> paramIds = new HashSet<>();

        Parameter[] params = method.getParameters();
        if (params != null && params.length > 0) {
            String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
            for (int i = 0; i < params.length; i++) {
                Parameter param = params[i];

                Class<?> paramClass = param.getType();
                ApiComment paramClassComment = paramClass.getAnnotation(ApiComment.class);
                if (paramClassComment != null) {
                    // 从参数的类的属性中获取注释信息。
                    List<ApiParamObject> paramsFromClass = toApiParams(
                            paramClass, defaultSeeClass);
                    for (ApiParamObject paramFromClass : paramsFromClass) {
                        if (paramIds.contains(paramFromClass.getId())) {
                            continue;
                        }
                        paramIds.add(paramFromClass.getId());
                        result.add(paramFromClass);
                    }
                } else {
                    // 从参数本身中获取注释信息。
                    String paramName;
                    if (paramNames != null) {
                        paramName = paramNames[i];
                    } else {
                        paramName = param.getName();
                    }

                    ApiParamObject apiParamObject = toApiParam(param,
                            paramName, param.getType(), defaultSeeClass);
                    if (apiParamObject == null) {
                        continue;
                    }

                    String paramId = apiParamObject.getId();
                    if (paramIds.contains(paramId)) {
                        String msg = "参数id值重复: " + paramId + ",所在方法: " + method;
                        throw new BeanDefinitionStoreException(msg);
                    }

                    paramIds.add(paramId);
                    result.add(apiParamObject);
                }
            }
        }
        return result;
    }

    /**
     * 从类的属性中获取注释信息。
     *
     * @param beanClass
     * @param defaultSeeClass
     * @return
     */
    public List<ApiParamObject> toApiParams(Class<?> beanClass, Class<?> defaultSeeClass) {
        List<ApiParamObject> result = new ArrayList<>();

        PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(beanClass);
        if (props == null || props.length == 0) {
            return result;
        }

        for (PropertyDescriptor prop : props) {
            if (Api2DocUtils.isFilter(prop, beanClass)) {
                continue;
            }

            String fieldName = prop.getName();

            Method readMethod = prop.getReadMethod();
            if (readMethod == null) {
                continue;
            }
            Class<?> fieldType = readMethod.getReturnType();

            Field field = Classes.getField(fieldName, beanClass);
            if (field == null) {
                continue;
            }

            ApiParamObject param = toApiParam(field, fieldName, fieldType,
                    defaultSeeClass);
            if (param == null) {
                continue;
            }

            result.add(param);
        }

        Collections.sort(result);

        return result;
    }

    ApiErrorObject getError(ApiError errorCode) {
        if (errorCode == null) {
            return null;
        }

        ApiErrorObject error = new ApiErrorObject();
        String code = errorCode.value();
        error.setId(code);
        error.setName(code);

        checkId(code);

        String comment = errorCode.comment();
        if (comment == null) {
            comment = BusinessException.getMessage(code);
        }
        if (comment == null) {
            comment = "";
        }
        error.setComment(comment);
        return error;
    }

    ApiParamObject toApiParam(
            AnnotatedElement element, String elementName,
            Class<?> elementType, Class<?> defaultSeeClass) {

        ApiParamObject apiParamObject = new ApiParamObject();

        ApiParamLocation.collects(apiParamObject, element);

        String id = apiParamObject.getId();
        checkId(id);

        String name = apiParamObject.getName();
        if (StringUtils.isEmpty(name)) {
            name = elementName;
        }
        apiParamObject.setName(name);

        apiParamObject.setId(name);

        ApiComment apiComment = element.getAnnotation(ApiComment.class);
        ApiCommentUtils.setApiComment(apiComment, defaultSeeClass, apiParamObject);

        apiParamObject.setSourceType(elementType);

        ApiDataType dataType = convertType(elementType);
        apiParamObject.setDataType(dataType);

        return apiParamObject;
    }

    String[] combine(String[] classPaths, String[] methodPaths) {
        if (classPaths == null || classPaths.length == 0) {
            return methodPaths;
        }

        List<String> paths = new ArrayList<>();
        for (String basePath : classPaths) {
            for (String srcPath : methodPaths) {
                String path = basePath + srcPath;
                if (paths.contains(path)) {
                    continue;
                }
                paths.add(path);
            }
        }
        return paths.toArray(new String[paths.size()]);
    }

    ApiDataType convertType(Class<?> paramType) {
        if (paramType == null) {
            return null;
        }
        paramType = Classes.toWrapType(paramType);

        if (paramType.equals(Boolean.class)) {
            return ApiDataType.BOOLEAN;
        }

        if (paramType.equals(Integer.class)
                || paramType.equals(Short.class)
                || paramType.equals(Byte.class)) {
            return ApiDataType.INT;
        }

        // Date 类型返回为 long 格式。
        ApiDataType dataType = DateConverter.dateAsLongType(paramType);
        if (dataType != null) {
            return dataType;
        }

        if (paramType.equals(Long.class)) {
            return ApiDataType.LONG;
        }

        if (paramType.equals(Float.class)
                || paramType.equals(Double.class)) {
            return ApiDataType.NUMBER;
        }

        if (paramType.equals(String.class)
                || paramType.equals(Character.class)
                || paramType.equals(StringBuffer.class)
                || paramType.equals(StringBuilder.class)) {
            return ApiDataType.STRING;
        }

        if (Classes.isInterface(paramType, Collection.class)) {
            return ApiDataType.ARRAY;
        }

        return ApiDataType.OBJECT;
    }

    private String[] getPath(RequestMapping mapping) {
        Set<String> allPaths = new HashSet<>();

        if (mapping != null) {
            String[] paths = mapping.path();
            if (paths != null && paths.length > 0) {
                allPaths.addAll(Arrays.asList(paths));
            }

            paths = mapping.value();
            if (paths != null && paths.length > 0) {
                allPaths.addAll(Arrays.asList(paths));
            }
        }

        return allPaths.toArray(new String[allPaths.size()]);
    }


    private void checkId(String id) {
        // TODO: CHECK id.
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocObjectFactory.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.Api2DocMocker;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.domain.ApiDataType;
import com.terran4j.commons.api2doc.domain.DateConverter;
import com.terran4j.commons.util.Classes;
import com.terran4j.commons.util.Enums;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.*;

/**
 * 根据类上的 Api2Doc 注解信息,创建 JavaBean、数组、列表等对象。
 */
public class Api2DocObjectFactory {

    private static final Logger log = LoggerFactory.getLogger(Api2DocObjectFactory.class);

    public static Object createObject(ApiDataType dataType,
                                      Class<?> elementType, String defaultValue) {
        if (dataType.isArrayType()) {
            int size = getArraySize(defaultValue, 1);
            return createList(elementType, size);
        } else if (dataType.isObjectType()) {
            return createBean(elementType);
        } else {
            if (DateConverter.isDateType(elementType)) {
                return DateConverter.dateAsLongValue(elementType);
            }
            if (StringUtils.hasText(defaultValue)) {
                return defaultValue;
            } else {
                return dataType.getDefault();
            }
        }
    }

    public static <T> T createBean(Class<T> clazz) {
        Stack<Class<?>> classStack = new Stack<Class<?>>();
        return createBean(clazz, null, classStack);
    }

    public static <E> List<E> createList(Class<E> clazz, int size) {
        Stack<Class<?>> classStack = new Stack<Class<?>>();
        return doCreateList(clazz, size, classStack);
    }

    public static <T> T[] createArray(Class<T> clazz, int size) {
        Stack<Class<?>> classStack = new Stack<Class<?>>();
        return doCreateArray(clazz, size, classStack);
    }

    private static <E> List<E> doCreateList(Class<E> clazz, int size, Stack<Class<?>> classStack) {
        List<E> list = new ArrayList<>();

        if (classStack.contains(clazz)) {
            return list;
        }

        for (int i = 0; i < size; i++) {
            E element = createBean(clazz, null, classStack);
            list.add(element);
        }
        return list;
    }

    private static <T> T[] doCreateArray(Class<T> clazz, int size, Stack<Class<?>> classStack) {
        if (size < 0) {
            return null;
        }
        T[] array = (T[]) Array.newInstance(clazz, size);

        if (classStack.contains(clazz)) {
            return array;
        }

        for (int i = 0; i < size; i++) {
            Object element = createBean(clazz, null, classStack);
            Array.set(array, i, element);
        }
        return array;
    }


    /**
     * 如果是 JavaBean 类,就创建这个 JavaBean 对象;<br>
     * 如果是 List / Array 对象,则什么都不做;<br>
     * 如果是 简单类型 对象,就创建符合这个类型的值。
     *
     * @param clazz 数据对象的类型。
     * @return 填充后的数据对象。
     */
    private static <T> T createBean(Class<T> clazz, String defaultValue, Stack<Class<?>> classStack) {
        if (clazz == null) {
            return null;
        }

        final ApiDataType dataType = ApiDataType.toDataType(clazz);
        if (dataType == null) {
            log.warn("无法识别的类型, class = {}", clazz);
            return null;
        }

        if (dataType.isArrayType()) {
            if (log.isInfoEnabled()) {
                log.info("数组类型,createBean 不处理, class = {}", clazz);
            }
            return null;
        }

        if (dataType.isSimpleType()) {
            if (defaultValue == null) {
                defaultValue = dataType.getDefault();
            }
            Object result = dataType.parseValue(defaultValue);
            result = adaptSimpleType(result, clazz);
            return (T) result;
        }

        // 处理 JavaBean 对象的情况。
        if (dataType.isObjectType()) {

            T object = null;
            try {
                object = clazz.newInstance();
            } catch (InstantiationException e) {
                log.warn("不能根据类创建对象,class = {}, 原因:{}", clazz, e.getMessage());
                return null;
            } catch (IllegalAccessException e) {
                log.warn("不能根据类创建对象,class = {}, 原因:{}", clazz, e.getMessage());
                return null;
            }
            if (object == null) {
                log.warn("不能根据类创建对象,class = {}", clazz);
                return null;
            }

            // 获取 JavaBean 的属性。
            PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(clazz);
            if (props == null || props.length == 0) { // 没有属性就不用处理。
                return object;
            }

            // 之前有过此类的信息,不用再次输出。
            if (classStack.contains(clazz)) {
                return object;
            }

            // 有属性,设置属性值。
            classStack.push(clazz);
            for (PropertyDescriptor prop : props) {
                String fieldName = prop.getName();
                try {
                    fillField(fieldName, object, classStack);
                } catch (Exception e) {
                    log.warn("给字段设值出错, class = {}, fieldName = {}", clazz, fieldName);
                }
            }
            classStack.pop();

            return object;
        }

        log.warn("无法识别的类型,class = {}", clazz);
        return null;
    }

    private static void fillField(String name, Object bean, Stack<Class<?>> classStack) {
        Class<?> clazz = Classes.getTargetClass(bean);

        PropertyDescriptor fieldProp = null;
        try {
            fieldProp = PropertyUtils.getPropertyDescriptor(bean, name);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        if (fieldProp == null) {
            throw new RuntimeException("field[" + name + "] NOT found in class: " + clazz);
        }
        if (Api2DocUtils.isFilter(fieldProp, clazz)) {
            return;
        }

        ApiComment classApiComment = clazz.getAnnotation(ApiComment.class);
        Class<?> defaultSeeClass = ApiCommentUtils.getDefaultSeeClass(
                classApiComment, null);

        String fieldName = fieldProp.getName();

        Method getMethod = fieldProp.getReadMethod();
        if (getMethod == null) {
            log.warn("没有 getter 方法, class = {}, fieldName = {}", clazz, fieldName);
            return;
        }

        Method setMethod = fieldProp.getWriteMethod();
        if (setMethod == null) {
            log.warn("没有 setter 方法, class = {}, fieldName = {}", clazz, fieldName);
            return;
        }

        Class<?> fieldClass = getMethod.getReturnType();
        Field field = Classes.getField(fieldName, clazz);
        if (field == null) {
            log.warn("找不到字段定义, class = {}, fieldName = {}", clazz, fieldName);
            return;
        }

        ApiDataType fieldDataType = ApiDataType.toDataType(fieldClass);
        if (fieldDataType == null) {
            log.warn("未知字段类型");
            return;
        }

        Object fieldValue = null;
        if (fieldDataType.isSimpleType()) {

            ApiComment apiComment = field.getAnnotation(ApiComment.class);
            String defaultValue = ApiCommentUtils.getSample(
                    apiComment, defaultSeeClass, fieldName);
            fieldValue = createBean(fieldClass, defaultValue, classStack);

            Class<?> paramType = setMethod.getParameterTypes()[0];
            fieldValue = adaptSimpleType(fieldValue, paramType);
        } else if (fieldDataType.isObjectType()) {
            fieldValue = createBean(fieldClass, null, classStack);
        } else if (fieldDataType.isArrayType()) {
            int size = 1;
            ApiComment apiComment = field.getAnnotation(ApiComment.class);
            if (apiComment != null) {
                String sizeText = ApiCommentUtils.getSample(
                        apiComment, defaultSeeClass, field.getName());
                size = getArraySize(sizeText, size);
            }
            Class<?> elementClass = getArrayElementClass(field);
            if (fieldClass.isArray()) {
                fieldValue = doCreateArray(elementClass, size, classStack);
            } else if (List.class.equals(fieldClass)) {
                fieldValue = doCreateList(elementClass, size, classStack);
            } else {
                log.warn("不支持的集合类型,目前只支持 Array OR List, class = {}, fieldName = {}" +
                        ", fieldClass = {}", clazz, fieldName, fieldClass);
            }
        }

        try {
            setMethod.invoke(bean, fieldValue);
        } catch (Exception e) {
            log.warn("调用 setter 方法失败, \n" +
                    "clazz = {}, \n" +
                    "setMethod = {}, \n" +
                    "fieldValue = {}, \n" +
                    "失败原因: {}", clazz, setMethod, fieldValue, e.getMessage());
        }
    }

    private static int getArraySize(String sizeText, int defaultValue) {
        if (StringUtils.hasText(sizeText)) {
            try {
                return Integer.parseInt(sizeText);
            } catch (Exception e) {
                log.warn("List 或 Array 类型的字段上," +
                        "@ApiComment 注解的 sample 属性应该是数字" +
                        "(代表它在 mock 时元素的个数), sample = {}", sizeText);
            }
        }
        return defaultValue;
    }

    private static Object adaptSimpleType(Object sourceValue, Class<?> targetType) {
        if (Long.class.equals(targetType) || long.class.equals(targetType)) {
            return Long.parseLong(sourceValue.toString());
        }
        if (Byte.class.equals(targetType) || byte.class.equals(targetType)) {
            return Byte.parseByte(sourceValue.toString());
        }
        if (Short.class.equals(targetType) || short.class.equals(targetType)) {
            return Short.parseShort(sourceValue.toString());
        }
        if (Float.class.equals(targetType) || float.class.equals(targetType)) {
            return Float.parseFloat(sourceValue.toString());
        }
        if (DateConverter.isDateType(targetType)) {
            return DateConverter.dateAsLongValue(targetType);
        }

        if (targetType.isEnum()) {
            return Enums.getEnumObject(targetType, sourceValue.toString());
        }

        return sourceValue;
    }

    private static final Class<?> getArrayElementClass(Field field) {

        Class<?> returnType = field.getType();
        if (returnType.isArray()) {
            Class<?> elementClass = returnType.getComponentType();
            return elementClass;
        }

        if (Classes.isInterface(returnType, Collection.class)) {
            Type type = field.getGenericType();
            Type elementType = Api2DocUtils.getGenericType(type);
            if (elementType instanceof Class<?>) {
                Class<?> elementClass = (Class<?>) elementType;
                return elementClass;
            }
        }

        log.warn("不支持的数组类型");
        return null;
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocProperties.java
================================================
package com.terran4j.commons.api2doc.impl;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class Api2DocProperties {

    @Value("${server.url:http://localhost:8080}")
    private String serverURL;

    @Value("${api2doc.showCurl:true}")
    private boolean showCurl = true;

    @Value("${service.name:}")
    private String serviceName;

    @Value("${api2doc.title:}")
    private String api2docTitle;

    @Value("${api2doc.icon:}")
    private String api2docIcon;

    public String getServerURL() {
        return serverURL;
    }

    public boolean isShowCurl() {
        return showCurl;
    }

    public String getServiceName() {
        return serviceName;
    }

    public String getApi2docTitle() {
        return api2docTitle;
    }

    public String getApi2docIcon() {
        return api2docIcon;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocService.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiFolderObject;
import com.terran4j.commons.util.value.KeyedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class Api2DocService {

    private static final Logger log = LoggerFactory.getLogger(Api2DocService.class);

    private static final String v = String.valueOf(System.currentTimeMillis());
	
	private final KeyedList<String, ApiFolderObject> folders = new KeyedList<>();
	
	public boolean hasFolder(String id) {
		return folders.containsKey(id);
	}
	
	public ApiFolderObject getFolder(String id) {
		return folders.get(id);
	}
	
	public void addFolder(ApiFolderObject folder) {
		if (folder == null) {
			throw new NullPointerException("ApiFolderObject is null");
		}
		folders.add(folder.getId(), folder);
	}
	
	public List<ApiFolderObject> getFolders() {
		return folders.getAll();
	}

    public String addAppDocVersion(String path) {
	    if (path.indexOf("?") > 0) {
	        return path + "&v=" + getAppDocVersion();
        } else {
            return path + "?v=" + getAppDocVersion();
        }
    }

    public String getAppDocVersion() {
        return v;
    }

    public String getComponentVersion() {
	    return v;
    }

    public ApiDocObject getDocObject(String folderId, String docId) throws Exception {
        ApiFolderObject folder = getFolder(folderId);
        if (folder == null) {
            log.warn("ApiFolder NOT Found: {}", folderId);
            return null;
        }

        ApiDocObject doc = folder.getDoc(docId);
        if (doc == null) {
            if (log.isWarnEnabled()) {
                log.warn("ApiDoc NOT Found: {}", folderId);
            }
            return null;
        }

        return doc;
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocUtils.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiObject;
import com.terran4j.commons.api2doc.domain.ApiParamLocation;
import com.terran4j.commons.api2doc.domain.ApiParamObject;
import com.terran4j.commons.restpack.RestPackIgnore;
import com.terran4j.commons.util.Classes;
import com.terran4j.commons.util.Encoding;
import com.terran4j.commons.util.Strings;
import com.terran4j.commons.util.error.BusinessException;
import com.terran4j.commons.util.value.ValueSource;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.*;

public class Api2DocUtils {

    public static String toURL(ApiDocObject doc, String serverURL) {
        if (doc == null) {
            throw new NullPointerException("doc is null.");
        }

        boolean hasGetMethod = false;
        RequestMethod[] methods = doc.getMethods();
        if (methods != null) {
            for (RequestMethod method : methods) {
                if (method == RequestMethod.GET) {
                    hasGetMethod = true;
                }
            }
        } else {
            hasGetMethod = true;
        }
        if (!hasGetMethod) {
            // TODO: 暂时不支持非 GET 的请求。
            return null;
        }

        String docURL = serverURL + doc.getPaths()[0];
        List<ApiParamObject> params = doc.getParams();
        Map<String, String> pathParams = new HashMap<>();
        Map<String, String> getParams = new HashMap<>();
        if (params != null) {
            for (ApiParamObject param : params) {
                if (param.getLocation() == ApiParamLocation.PathVariable) {
                    String value = param.getSample().getValue();
                    if (StringUtils.isEmpty(value)) {
                        value = param.getDataType().getDefault();
                    }
                    pathParams.put(param.getId(), value);
                }
                if (param.getLocation() == ApiParamLocation.RequestParam) {
                    String value = param.getSample().getValue();
                    if (StringUtils.isEmpty(value)) {
                        continue;
                    }
                    getParams.put(param.getId(), value);
                }
            }
        }

        if (pathParams.size() > 0) {
            docURL = Strings.format(docURL, new ValueSource<String, String>() {

                @Override
                public String get(String key) {
                    String value = pathParams.get(key);
                    if (value == null) {
                        return null;
                    }
                    return encode(value);
                }
            }, "{", "}", null);
        }

        if (getParams.size() > 0) {

            List<String> keys = new ArrayList<>();
            keys.addAll(getParams.keySet());
            keys.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });

            StringBuffer sb = new StringBuffer();
            for (String key : keys) {
                String value = getParams.get(key);
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(key).append("=").append(encode(value));
            }
            docURL = docURL + "?" + sb.toString();
        }

        return docURL;
    }

    private static String encode(String text) {
        try {
            return URLEncoder.encode(text, Encoding.UTF8.getName());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

//    public static final void setApiComment(ApiComment apiComment, ApiObject apiObject) {
//        if (apiComment != null && StringUtils.hasText(apiComment.value())) {
//            String commentText = getComment(apiComment);
//            apiObject.setComment(commentText);
//        }
//        if (apiComment != null && StringUtils.hasText(apiComment.sample())) {
//            if (StringUtils.hasText(apiComment.sample())) {
//                apiObject.setSample(apiComment.sample());
//            }
//        }
//    }
//
//    public static final String getComment(ApiComment apiComment) {
//        String comment = apiComment.value();
//        if (StringUtils.isEmpty(comment)) {
//            return null;
//        }
//        return comment.trim();
//    }
//
//    public static final String getSample(ApiComment apiComment, Class<?> clazz) throws BusinessException {
//        String sample = apiComment.sample();
//        if (StringUtils.isEmpty(sample)) {
//            return null;
//        }
//        return sample.trim();
//
////        if (!(sample.startsWith("@") && sample.endsWith("@"))) {
////            return sample.replaceAll("\n", "<br/>");
////        }
////
////        String fileName = sample.substring(1, sample.length() - 1);
////        String json = Strings.getString(clazz, fileName);
////        if (StringUtils.isEmpty(json)) {
////            throw new BusinessException(ErrorCodes.CONFIG_ERROR)
////                    .put("package", clazz.getPackage().getName())
////                    .put("fileName", fileName)
////                    .setMessage("在包 ${package} 中找不到文件: ${fileName}");
////        }
////        return json;
//    }

    public static final Class<?> getArrayElementClass(Method method) {

        Class<?> returnType = method.getReturnType();
        if (returnType.isArray()) {
            Class<?> elementClass = returnType.getComponentType();
            return elementClass;
        }

        if (Classes.isInterface(returnType, Collection.class)) {
            Type gType = method.getGenericReturnType();
            Type elementType = getGenericType(gType);
            if (elementType instanceof Class<?>) {
                Class<?> elementClass = (Class<?>) elementType;
                return elementClass;
            }
        }

        return null;
    }

    public static final Type getGenericType(Type gType) {
        // 如果gType是泛型类型对像。
        if (gType instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) gType;
            // 获得泛型类型的泛型参数
            Type[] gArgs = pType.getActualTypeArguments();
            return gArgs[gArgs.length - 1];
        } else {
            System.out.println("获取泛型信息失败");
            return null;
        }
    }

    public static final boolean isFilter(
            PropertyDescriptor prop, Class<?> clazz) {

        String fieldName = prop.getName();

        // class 只是 Java 对象自带的  Object.getClass() 方法,忽略掉。
        if ("class".equals(fieldName)) {
            return true;
        }

        // 忽略掉需要忽略的字段。
        Field field = Classes.getField(fieldName, clazz);
        if (field != null) {
            if (field.getAnnotation(RestPackIgnore.class) != null) {
                return true;
            }
            if (field.getAnnotation(JsonIgnore.class) != null) {
                return true;
            }
        }

        return false;
    }
}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ApiCommentUtils.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.annotations.ApiComment;
import com.terran4j.commons.api2doc.domain.ApiObject;
import com.terran4j.commons.util.Classes;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class ApiCommentUtils {


    public static Class<?> getDefaultSeeClass(ApiComment apiComment,
                                              Class<?> previousSeeClass) {
        if (apiComment == null) {
            return previousSeeClass;
        }

        Class<?> defaultSeeClass = apiComment.seeClass();
        if (defaultSeeClass == Object.class) {
            return previousSeeClass;
        }

        return defaultSeeClass;
    }

    public static final void setApiComment(ApiComment apiComment,
                                           Class<?> defaultSeeClass, ApiObject apiObject) {
        String comment = getComment(apiComment, defaultSeeClass, apiObject.getId());
        if (comment != null) {
            apiObject.setComment(comment);
        }
        String sample = getSample(apiComment, defaultSeeClass, apiObject.getId());
        if (sample != null) {
            apiObject.setSample(sample);
        }
    }

//    public static final ApiComment getComment(Field field, Class<?> defaultSeeClass) {
//        ApiComment apiComment = field.getAnnotation(ApiComment.class);
//        if (apiComment !)
//    }

    public static final String getComment(ApiComment apiComment,
                                          Class<?> defaultSeeClass, String defaultName) {

        if (apiComment != null) {
            String comment = apiComment.value();
            if (StringUtils.hasText(comment)) {
                return comment.trim();
            }
        }

        ApiComment seeComment = getSeeApiComment(
                apiComment, defaultSeeClass, defaultName);
        if (seeComment == null) {
            return null;
        }

        String comment = seeComment.value();
        if (StringUtils.hasText(comment)) {
            return comment.trim();
        }

        return null;
    }

    public static final String getSample(ApiComment apiComment,
                                         Class<?> defaultSeeClass, String defaultName) {
        if (apiComment != null) {
            String sample = apiComment.sample();
            if (StringUtils.hasText(sample)) {
                return sample.trim();
            }
        }

        ApiComment seeComment = getSeeApiComment(
                apiComment, defaultSeeClass, defaultName);
        if (seeComment == null) {
            return null;
        }

        String sample = seeComment.sample();
        if (StringUtils.hasText(sample)) {
            return sample.trim();
        }

        return null;
    }

    /**
     * 获取可参照的 @ApiComment 注解对象。
     * @param apiComment
     * @param defaultSeeClass
     * @param defaultSeeField
     * @return
     */
    private static ApiComment getSeeApiComment(
            ApiComment apiComment, Class<?> defaultSeeClass, String defaultSeeField) {

        Class<?> seeClass = null;
        if (apiComment != null ) {
            seeClass = apiComment.seeClass();
        }
        if (seeClass == null || seeClass == Object.class) {
            seeClass = defaultSeeClass;
        }
        if (seeClass == null || seeClass == Object.class) {
            return null;
        }

        String seeField = null;
        if (apiComment != null) {
            seeField = apiComment.seeField();
        }
        if (StringUtils.isEmpty(seeField)) {
            seeField = defaultSeeField;
        }
        if (StringUtils.isEmpty(seeField)) {
            return null;
        }

        // 记录引用过的 seeClass, 用于循环引用检测。
        List<Class<?>> path = new ArrayList<>();
        Field field = null;
        ApiComment seeComment = null;
        while (seeClass != null) {

            // 循环引用检测。
            if (path.contains(seeClass)) {
                StringBuffer sb = new StringBuffer();
                sb.append("@ApiComment 中的 seeClass 不允许循环引用:");
                for (int i = 0; i < path.size(); i++) {
                    if (i > 0) {
                        sb.append(" --> ");
                    }
                    sb.append(seeClass.getSimpleName());
                }
                throw new RuntimeException(sb.toString());
            }
            path.add(seeClass);

            // 寻找匹配字段中的 ApiComment 。
            field = Classes.getField(seeField, seeClass);
            if (field != null) {
                seeComment = field.getAnnotation(ApiComment.class);
                if (seeComment != null) {
                    return seeComment;
                }
            }

            ApiComment parentApiComment = seeClass.getAnnotation(ApiComment.class);
            if (parentApiComment == null) {
                break;
            }
            seeClass = parentApiComment.seeClass();
        }

        return null;
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ClasspathFreeMarker.java
================================================
package com.terran4j.commons.api2doc.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import com.terran4j.commons.util.Encoding;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

@Service
public class ClasspathFreeMarker {

	private final Map<String, Template> templates = new HashMap<String, Template>();

	private final Configuration freeMarker;

	public ClasspathFreeMarker() {
		super();

		try {
			freeMarker = new Configuration(Configuration.VERSION_2_3_25);
			freeMarker.setDefaultEncoding(Encoding.UTF8.getName());
			TemplateLoader ctl = new ClassTemplateLoader(getClass(), "/");
			freeMarker.setTemplateLoader(ctl);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private String getPath(Class<?> clazz, String fileName) {
		String path = clazz.getPackage().getName().replace('.', '/') + "/" + fileName;
		return path;
	}

	public final Template getTemplate(Class<?> clazz, String fileName) {
		String path = getPath(clazz, fileName);

		Template template = templates.get(path);
		if (template != null) {
			return template;
		}

		synchronized (ClasspathFreeMarker.class) {
			template = templates.get(path);
			if (template != null) {
				return template;
			}

			try {
				template = freeMarker.getTemplate(path);
				templates.put(path, template);
				return template;
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}

	public final String build(Template template, Map<String, Object> model) //
			throws IOException, TemplateException {
		if (!templates.containsValue(template)) {
			String msg = "Can't build from the tempate which NOT get by calling this method:\n"
					+ "ClasspathFreeMarker.getTemplate(Class<?> clazz, String fileName)";
			throw new UnsupportedOperationException(msg);
		}
		String html = FreeMarkerTemplateUtils.processTemplateIntoString( //
				template, model);
		return html;
	}

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/CurlBuilder.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiParamLocation;
import com.terran4j.commons.api2doc.domain.ApiParamObject;
import com.terran4j.commons.util.Encoding;
import com.terran4j.commons.util.Strings;
import com.terran4j.commons.util.value.KeyedList;
import com.terran4j.commons.util.value.ValueSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class CurlBuilder {

    private static final Logger log = LoggerFactory.getLogger(CurlBuilder.class);

    private static final String enter = " \\\n";

    public static String toCurl(ApiDocObject docObject, String serverURL) {

        final List<ApiParamObject> allParams = docObject.getParams();
        final KeyedList<String, String> headers = new KeyedList<>();
        final KeyedList<String, String> params = new KeyedList<>();
        final KeyedList<String, String> cookies = new KeyedList<>();
        final Map<String, String> pathVars = new HashMap<>();
        final KeyedList<String, String> parts = new KeyedList<>();

        if (allParams.size() > 0) {
            for (ApiParamObject param : allParams) {
                String key = param.getId();

                String value = param.getSample().getValue();
                if (StringUtils.isEmpty(value)) {
                    Class<?> paramType = param.getSourceType();
                    if (paramType == String.class) {
                        value = key;
                    } else {
                        value = param.getDataType().getDefault();
                    }
                }

                if (param.getLocation() == ApiParamLocation.RequestParam) {
                    params.add(key, value);
                }
                if (param.getLocation() == ApiParamLocation.PathVariable) {
                    pathVars.put(key, value);
                }
                if (param.getLocation() == ApiParamLocation.RequestHeader) {
                    headers.add(key, value);
                }
                if (param.getLocation() == ApiParamLocation.CookieValue) {
                    cookies.add(key, value);
                }
                if (param.getLocation() == ApiParamLocation.RequestPart) {
                    parts.add(key, value);
                }
            }
        }

        RequestMethod[] requestMethods = docObject.getMethods();
        RequestMethod requestMethod = requestMethods[0];
        StringBuilder sb = new StringBuilder("curl");
        if (parts.size() == 0) {
            // 没有上传文件,才指定方法。
            sb.append(" -X ").append(requestMethod.name());
        }
        sb.append(enter);

        // 将 Header 参数拼接起来。
        if (headers.size() > 0) {
            for (int i = 0; i < headers.size(); i++) {
                String key = headers.getKey(i);
                String value = headers.get(i);
                sb.append(" -H \"").append(key).append(": ").append(value)
                        .append("\"").append(enter);
            }
        }

        if (cookies.size() > 0) {
            sb.append(" -b \"");
            sb.append(joinText(cookies, ";", "="));
            sb.append("\"").append(enter);
        }

        // 将 URL 中的 {xx} 变量用参数的示例值代替。
        String url = serverURL + docObject.getPaths()[0];
        if (pathVars.size() > 0) {
            ValueSource<String, String> vars = new ValueSource<String, String>() {
                @Override
                public String get(String key) {
                    return encode(pathVars.get(key));
                }
            };
            url = Strings.format(url, vars, "{", "}", null);
        }

        // 将“参数”拼起来。
        if (params.size() > 0) {
            if (parts.size() > 0) {
                // 参数按 multipart 的方法传。
                for (int i = 0; i < params.size(); i++) {
                    String key = params.getKey(i);
                    String value = params.get(i);
                    sb.append(" -F \"").append(key).append("=").append(value)
                            .append("\"").append(enter);
                }
            } else if (requestMethod == RequestMethod.POST) {
                // 参数按 post 的方法传。
                sb.append(" -d \"").append(joinText(params, "&", "="))
                        .append("\"").append(enter);
            } else {
                // 参数附加到 URL 后面。
                url += ("?" + joinText(params, "&", "="));
            }
        }

        // 追加 multipart 参数。
        if (parts.size() > 0) {
            for (int i = 0; i < parts.size(); i++) {
                String key = parts.getKey(i);
                String value = parts.get(i);
                sb.append(" -F \"").append(key).append("=@").append(value)
                        .append("\"").append(enter);
            }
        }

        // 将 URL 拼接起来。
        sb.append(" \"").append(url).append("\"");

        String curl = sb.toString();
        if (log.isInfoEnabled()) {
            log.info("doc[{}]'s curl:\n{}", docObject.getId(), curl);
        }
        return curl;
    }

    /**
     * 连接成字符串,并将 value 值进行 URL 编码。
     */
    public static final String joinText(KeyedList<String, String> params,
                                        String joiner, String splitter) {
        StringBuffer sb = new StringBuffer();
        boolean first = true;
        Iterator<String> it = params.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = params.get(key);
            if (!first) {
                sb.append(joiner);
            }
            sb.append(key).append(splitter).append(encode(value));
            first = false;
        }
        return sb.toString();
    }

    private static String encode(String value) {
        try {
            // 对于空格的编码,有的地方不认 + ,所以统一转成: %20
            String str = URLEncoder.encode(value, Encoding.UTF8.getName());
            return str.replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

}


================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocMenuBuilder.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.controller.MenuData;
import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiFolderObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class DocMenuBuilder {

    @Autowired
    private Api2DocService apiDocService;

    public List<MenuData> getMenuGroups() {
        List<MenuData> menuGroups = new ArrayList<>();

        List<ApiFolderObject> folders = apiDocService.getFolders();
        if (folders == null || folders.size() == 0) {
            return menuGroups;
        }

        for (ApiFolderObject folder : folders) {
            MenuData menuGroup = getMenuGroup(folder);
            menuGroups.add(menuGroup);
        }

        Collections.sort(menuGroups);

        return menuGroups;
    }

    public MenuData getMenuGroup(ApiFolderObject folder) {
        String folderId = folder.getId();
        String folderName = folder.getName();

        MenuData menuGroup = new MenuData();
        menuGroup.setId(folderId);
        menuGroup.setIndex(folderId);
        menuGroup.setName(folderName);
        menuGroup.setFolder(true);
        menuGroup.setOrder(folder.getOrder());

        List<MenuData> children = new ArrayList<>();

        Map<String, String> mds = folder.getMds();
        if (mds != null && mds.size() > 0) {
            for (String md : mds.values()) {
                MenuData menu = getMenu(md, folderId);
                children.add(menu);
            }
        }

        List<ApiDocObject> docs = folder.getDocs();
        if (docs != null) {
            for (ApiDocObject doc : docs) {
                MenuData menu = getMenu(doc, folderId);
                children.add(menu);
            }
        }

        Collections.sort(children);
        menuGroup.setChildren(children);
        return menuGroup;
    }

    public MenuData getMenu(String mdFileName, String folderId) {
        int offset = mdFileName.indexOf("-");
        String orderText = mdFileName.substring(0, offset);
        int order = Integer.parseInt(orderText);
        String docName = mdFileName.substring(offset + 1,
                mdFileName.length() - ".md".length());
        String docId = ApiFolderObject.name2Id(mdFileName);
        MenuData menu = new MenuData();

        String pageId = "md-" + folderId + "-" + docId;
        menu.setId(pageId);
        menu.setIndex(pageId);
        String url = getPageURL(pageId);
        menu.setUrl(url);

        menu.setFolder(false);
        menu.setName(docName);
        menu.setOrder(order);

        return menu;
    }

    public MenuData getMenu(ApiDocObject doc, String folderId) {
        MenuData menu = new MenuData();

        String pageId = "api-" + folderId + "-" + doc.getId();
        menu.setId(pageId);
        menu.setIndex(pageId);
        String url = getPageURL(pageId);
        menu.setUrl(url);

        menu.setFolder(false);
        menu.setName(doc.getName());
        menu.setOrder(doc.getOrder());

        return menu;
    }

    private String getPageURL(String pageId) {
        try {
            String p = URLEncoder.encode(pageId, "UTF-8");
            String path = "/api2doc/home.html?p=" + p;
            return apiDocService.addAppDocVersion(path);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Can't encoding: " + pageId, e);
        }
    }
}

================================================
FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocPageBuilder.java
================================================
package com.terran4j.commons.api2doc.impl;

import com.terran4j.commons.api2doc.domain.ApiDocObject;
import com.terran4j.commons.api2doc.domain.ApiFolderObject;
import com.terran4j.commons.restpack.HttpResult;
import com.terran4j.commons.restpack.config.RestPackConfiguration;
import com.terran4j.commons.util.Strings;
import com.vladsch.flexmark.ast.Node;
import com.vladsch.flexmark.ext.spec.example.SpecExampleExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.parser.ParserEmulationProfile;
import com.vladsch.flexmark.util.KeepType;
import com.vladsch.flexmark.util.options.MutableDataSet;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Service
public class DocPageBuilder {

    private static final Logger log = LoggerFactory.getLogger(DocPageBuilder.class);

    private static final String FILE_DOC_MD = "doc.md.ftl";

    @Autowired
    private Api2DocProperties api2DocProperties;

    @Autowired
    private Api2DocService apiDocService;

    @Autowired
    private ClasspathFreeMarker freeMarker;

    private Template mdTemplate = null;

    private Parser parser = null;

    private HtmlRenderer renderer = null;

    @PostConstruct
    public void init() {
        try {
            mdTemplate = freeMarker.getTemplate(DocPageBuilder.class, FILE_DOC_MD);

            MutableDataSet options = new MutableDataSet();
            options.setFrom(ParserEmulationProfile.GITHUB_DOC);
            options.set(Parser.EXTENSIONS, Arrays.asList(
                    TablesExtension.create(), // 表格渲染插件。
                    SpecExampleExtension.create() // 代码渲染插件。
            ));

            // References compatibility
            options.set(Parser.REFERENCES_KEEP, KeepType.LAST);

            // Set GFM table parsing options
            options.set(TablesExtension.COLUMN_SPANS, false) //
                    .set(TablesExtension.MIN_HEADER_ROWS, 1) //
                    .set(TablesExtension.MAX_HEADER_ROWS, 1) //
                    .set(TablesExtension.APPEND_MISSING_COLUMNS, true) //
                    .set(TablesExtension.DISCARD_EXTRA_COLUMNS, true) //
                    .set(TablesExtension.WITH_CAPTION, false) //
                  
Download .txt
gitextract_jq1qgnkm/

├── .gitignore
├── LICENSE
├── README.md
├── build.txt
├── commons-api2doc/
│   ├── .gitignore
│   ├── README.md
│   ├── doc/
│   │   ├── TODO.md
│   │   └── aboutCurl.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── api2doc/
│       │   │                   ├── Api2DocMocker.java
│       │   │                   ├── annotations/
│       │   │                   │   ├── Api2Doc.java
│       │   │                   │   ├── ApiComment.java
│       │   │                   │   ├── ApiError.java
│       │   │                   │   └── ApiErrors.java
│       │   │                   ├── codewriter/
│       │   │                   │   ├── CodeConfig.java
│       │   │                   │   ├── CodeOutput.java
│       │   │                   │   ├── CodeUtils.java
│       │   │                   │   ├── EnumCodeWriter.java
│       │   │                   │   ├── FileCodeOutput.java
│       │   │                   │   ├── JavaBeanCodeWriter.java
│       │   │                   │   ├── MemoryCodeOutput.java
│       │   │                   │   └── RetrofitCodeWriter.java
│       │   │                   ├── config/
│       │   │                   │   ├── Api2DocConfiguration.java
│       │   │                   │   └── EnableApi2Doc.java
│       │   │                   ├── controller/
│       │   │                   │   ├── Api2DocController.java
│       │   │                   │   ├── ApiEntry.java
│       │   │                   │   ├── ApiInfo.java
│       │   │                   │   ├── ApiMetaController.java
│       │   │                   │   └── MenuData.java
│       │   │                   ├── domain/
│       │   │                   │   ├── ApiDataType.java
│       │   │                   │   ├── ApiDocObject.java
│       │   │                   │   ├── ApiDocUtils.java
│       │   │                   │   ├── ApiErrorObject.java
│       │   │                   │   ├── ApiFolderObject.java
│       │   │                   │   ├── ApiObject.java
│       │   │                   │   ├── ApiParamLocation.java
│       │   │                   │   ├── ApiParamObject.java
│       │   │                   │   ├── ApiResultObject.java
│       │   │                   │   └── DateConverter.java
│       │   │                   ├── impl/
│       │   │                   │   ├── Api2DocCollector.java
│       │   │                   │   ├── Api2DocObjectFactory.java
│       │   │                   │   ├── Api2DocProperties.java
│       │   │                   │   ├── Api2DocService.java
│       │   │                   │   ├── Api2DocUtils.java
│       │   │                   │   ├── ApiCommentUtils.java
│       │   │                   │   ├── ClasspathFreeMarker.java
│       │   │                   │   ├── CurlBuilder.java
│       │   │                   │   ├── DocMenuBuilder.java
│       │   │                   │   ├── DocPageBuilder.java
│       │   │                   │   ├── FlexibleString.java
│       │   │                   │   └── MappingMethod.java
│       │   │                   └── meta/
│       │   │                       ├── ApiMetaService.java
│       │   │                       ├── ClassMeta.java
│       │   │                       ├── MethodMeta.java
│       │   │                       └── ParamMeta.java
│       │   └── resources/
│       │       ├── api2doc/
│       │       │   └── welcome.md
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── api2doc/
│       │       │               ├── codewriter/
│       │       │               │   ├── bean.java.ftl
│       │       │               │   ├── enum.java.ftl
│       │       │               │   └── retrofit.java.ftl
│       │       │               └── impl/
│       │       │                   └── doc.md.ftl
│       │       ├── static/
│       │       │   └── api2doc/
│       │       │       ├── css/
│       │       │       │   ├── doc.less
│       │       │       │   ├── home.less
│       │       │       │   ├── md.less
│       │       │       │   └── test.less
│       │       │       ├── flexible-lite/
│       │       │       │   └── flexible-lite-1.0.js
│       │       │       ├── less/
│       │       │       │   └── less-1.7.0.js
│       │       │       ├── test.html
│       │       │       └── vue/
│       │       │           └── vue-2.5.10.js
│       │       └── templates/
│       │           └── api2doc/
│       │               ├── doc.ftl
│       │               └── home.ftl
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           ├── demo/
│           │           │   └── api2doc/
│           │           │       ├── Api2DocDemoApp.java
│           │           │       ├── CodeGenerator.java
│           │           │       ├── FileInfo.java
│           │           │       ├── ShowMappingController.java
│           │           │       ├── ShowParamController.java
│           │           │       ├── ShowResultController.java
│           │           │       ├── User.java
│           │           │       ├── UserController.java
│           │           │       ├── UserController1.java
│           │           │       ├── UserController2.java
│           │           │       ├── UserController3.java
│           │           │       ├── UserGroup.java
│           │           │       └── UserType.java
│           │           └── test/
│           │               └── api2doc/
│           │                   ├── Api2DocCollectorTest.java
│           │                   ├── Api2DocObjectFactoryTest.java
│           │                   ├── Api2DocUtilsTest.java
│           │                   ├── ApiCommentUtilsTest.java
│           │                   ├── ApiResultObjectTest.java
│           │                   ├── Application.java
│           │                   ├── BaseApi2DocTest.java
│           │                   ├── CurlBuilderTest.java
│           │                   ├── JavaBeanCodeWriterTest.java
│           │                   ├── MyBean.java
│           │                   ├── ParseApiCommentOnMethod.java
│           │                   ├── ParseApiCommentOnParam.java
│           │                   ├── ParseApiCommentOnSeeClass.java
│           │                   ├── ParseApiCommentOnSeeClassLoop.java
│           │                   ├── ParseEnumTest.java
│           │                   ├── ParseListBeanTest.java
│           │                   ├── ResultSourceTypeTest.java
│           │                   └── ToMockResultTest.java
│           └── resources/
│               ├── api2doc/
│               │   ├── demo3/
│               │   │   ├── 1-项目简介.md
│               │   │   ├── 11-接口1的补充说明.md
│               │   │   ├── 2-技术架构.md
│               │   │   ├── 21-接口2的补充说明.md
│               │   │   └── 3-应用场景.md
│               │   └── welcome.md
│               └── application.yml
├── commons-armq/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── armq/
│       │                       ├── ArmqConfig.java
│       │                       ├── ConsumerConfig.java
│       │                       ├── MessageConsumer.java
│       │                       ├── MessageEntity.java
│       │                       ├── MessageService.java
│       │                       └── impl/
│       │                           ├── MessageConsumerTask.java
│       │                           ├── MessageConsumerTransfer.java
│       │                           └── MessageServiceImpl.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           └── commons/
│           │               └── test/
│           │                   └── armq/
│           │                       ├── ArmqTestApp.java
│           │                       ├── Normal.java
│           │                       ├── NormalTopicTest.java
│           │                       ├── Producer.java
│           │                       └── SendTest.java
│           └── resources/
│               └── .gitignore
├── commons-dsql/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── dsql/
│       │                       ├── DsqlExecutor.java
│       │                       ├── DsqlModifying.java
│       │                       ├── DsqlQuery.java
│       │                       ├── DsqlRepository.java
│       │                       ├── EnableDsqlRepositories.java
│       │                       ├── QueryBean.java
│       │                       ├── config/
│       │                       │   └── DsqlConfiguration.java
│       │                       └── impl/
│       │                           ├── CompositeBeanRowMapper.java
│       │                           ├── DsqlBuilder.java
│       │                           ├── DsqlExecutorImpl.java
│       │                           ├── DsqlRepositoryBeanFactory.java
│       │                           ├── DsqlRepositoryConfigRegistrar.java
│       │                           ├── DsqlRepositoryProxy.java
│       │                           └── SqlInfo.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       ├── demo/
│                       │   └── dsql/
│                       │       ├── Address.java
│                       │       ├── AddressDAO.java
│                       │       ├── AddressDistance.java
│                       │       ├── AddressDistanceDAO.java
│                       │       ├── AddressQuery.java
│                       │       ├── address-count.sql.ftl
│                       │       ├── address-delete-nearest.sql.ftl
│                       │       ├── address-list.sql.ftl
│                       │       ├── address-nearest-2.sql.ftl
│                       │       ├── address-nearest.sql.ftl
│                       │       ├── address-update-nearest.sql.ftl
│                       │       ├── appdsql/
│                       │       │   └── DsqlDemoApplication.java
│                       │       └── appjpa/
│                       │           └── JpaDemoApplication.java
│                       └── test/
│                           └── dsql/
│                               ├── BaseDsqlTest.java
│                               ├── DsqlAutoTest.java
│                               ├── DsqlModifyingTest.java
│                               ├── DsqlQueryTest.java
│                               ├── dao/
│                               │   ├── Location.java
│                               │   ├── LocationDAO.java
│                               │   └── LocationQuery.java
│                               ├── dao1/
│                               │   ├── LocationDsqlDAO.java
│                               │   ├── delete-nearest.sql.ftl
│                               │   └── update-nearest.sql.ftl
│                               ├── dao2/
│                               │   ├── LocationDistance.java
│                               │   ├── LocationDistanceDAO.java
│                               │   ├── location-nearest.sql.ftl
│                               │   └── locations.sql.ftl
│                               ├── dao3/
│                               │   ├── DistancedLocation.java
│                               │   ├── DistancedLocationDAO.java
│                               │   ├── location-count.sql.ftl
│                               │   └── locations.sql.ftl
│                               └── dao4/
│                                   ├── LocationAutoDAO.java
│                                   ├── countLocation.sql.ftl
│                                   ├── getLocations.sql.ftl
│                                   └── getNearestLocation.sql.ftl
├── commons-hedis/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               ├── commons/
│       │               │   └── hedis/
│       │               │       ├── cache/
│       │               │       │   ├── CacheService.java
│       │               │       │   ├── JedisCacheService.java
│       │               │       │   └── RedisTemplateCacheService.java
│       │               │       ├── config/
│       │               │       │   ├── EnableHedis.java
│       │               │       │   └── HedisConfiguration.java
│       │               │       ├── dschedule/
│       │               │       │   ├── DScheduling.java
│       │               │       │   ├── DSchedulingAspect.java
│       │               │       │   ├── JobExeInfo.java
│       │               │       │   └── ScheduleContext.java
│       │               │       └── dsyn/
│       │               │           ├── DSynchArgs.java
│       │               │           ├── DSynchronized.java
│       │               │           ├── DSynchronizedAspect.java
│       │               │           └── Server.java
│       │               └── mock/
│       │                   └── hedis/
│       │                       ├── MockCacheService.java
│       │                       └── MockHedisConfig.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       ├── demo/
│                       │   └── hedis/
│                       │       ├── CountService.java
│                       │       ├── DSynchronizedCountService.java
│                       │       ├── DemoCacheService.java
│                       │       ├── HedisDemoApp.java
│                       │       ├── LoopIncrementJob.java
│                       │       └── User.java
│                       └── test/
│                           └── hedis/
│                               ├── BaseSpringBootTest.java
│                               ├── BaseTestExecutionListener.java
│                               ├── CacheAnnoTest.java
│                               ├── JedisCacheServiceTest.java
│                               ├── MockitoInitializer.java
│                               ├── RedisTestConfig.java
│                               ├── RedissonClientTest.java
│                               ├── SchedulingApplication.java
│                               └── dsyn/
│                                   ├── BaseCacheTest.java
│                                   ├── CacheTestApplication.java
│                                   ├── CountService.java
│                                   ├── DSynchronizedService.java
│                                   ├── DSynchronizedTest.java
│                                   ├── Home.java
│                                   └── HomeService.java
├── commons-hi/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── hi/
│       │                       ├── Action.java
│       │                       ├── ApacheHttpClientBuilder.java
│       │                       ├── Api2DocSupport.java
│       │                       ├── AssertResponseFailedException.java
│       │                       ├── HttpClient.java
│       │                       ├── HttpClientListener.java
│       │                       ├── HttpErrorCode.java
│       │                       ├── HttpErrorCode.properties
│       │                       ├── HttpException.java
│       │                       ├── HttpRequest.java
│       │                       ├── Param.java
│       │                       ├── Request.java
│       │                       ├── Response.java
│       │                       ├── Session.java
│       │                       ├── WrappedResponse.java
│       │                       ├── Write.java
│       │                       └── WriteTo.java
│       └── test/
│           └── java/
│               ├── application.yml
│               ├── com/
│               │   └── terran4j/
│               │       ├── demo/
│               │       │   └── hi/
│               │       │       ├── Calculator.java
│               │       │       ├── CalculatorController.java
│               │       │       ├── HttpClientApp.java
│               │       │       └── demo.json
│               │       └── test/
│               │           └── hi/
│               │               ├── BaseHiTest.java
│               │               ├── HttpClientTest.java
│               │               ├── HttpClientTest.json
│               │               ├── TestHiApp.java
│               │               ├── api2doc/
│               │               │   ├── Api2DocApp.java
│               │               │   ├── Api2DocDemoController.java
│               │               │   ├── Api2DocSupportTest.java
│               │               │   └── MultiplyObject.java
│               │               └── exe/
│               │                   ├── ExeController.java
│               │                   ├── ExeTest.java
│               │                   ├── ExeTest.json
│               │                   └── PlusObject.java
│               ├── example.json
│               ├── hi.json
│               └── http.config.json
├── commons-jfinger/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── jfinger/
│       │       │               ├── Command.java
│       │       │               ├── CommandDefine.java
│       │       │               ├── CommandErrorCode.java
│       │       │               ├── CommandException.java
│       │       │               ├── CommandExecutor.java
│       │       │               ├── CommandGroup.java
│       │       │               ├── CommandGroupDefine.java
│       │       │               ├── CommandGroups.java
│       │       │               ├── CommandInterpreter.java
│       │       │               ├── CommandOption.java
│       │       │               ├── CommandOptionDefine.java
│       │       │               ├── CommandOptionType.java
│       │       │               ├── EnableJFinger.java
│       │       │               ├── Encoding.java
│       │       │               ├── JFingerConfiguration.java
│       │       │               ├── OptionType.java
│       │       │               ├── builtin/
│       │       │               │   ├── LogCommand.java
│       │       │               │   ├── SpringCommand.java
│       │       │               │   └── SystemCommand.java
│       │       │               └── impl/
│       │       │                   ├── BackCommandException.java
│       │       │                   ├── CommandInterpreterImpl.java
│       │       │                   ├── CommandLineApplicationListener.java
│       │       │                   ├── CommandLineService.java
│       │       │                   ├── CommandLineTask.java
│       │       │                   ├── DynMethodCommandExecutor.java
│       │       │                   └── Util.java
│       │       └── error.properties
│       └── test/
│           └── java/
│               ├── cmd.txt
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── commons/
│                               └── jfinger/
│                                   └── JFingerTestApplication.java
├── commons-reflux/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── reflux/
│       │                       ├── EnableReflux.java
│       │                       ├── Message.java
│       │                       ├── OnMessage.java
│       │                       ├── RefluxClient.java
│       │                       ├── RefluxErrorCode.java
│       │                       ├── RefluxServer.java
│       │                       ├── Reply.java
│       │                       ├── client/
│       │                       │   ├── ClientConnection.java
│       │                       │   ├── EnableRefluxClient.java
│       │                       │   ├── MessageHandler.java
│       │                       │   ├── RefluxClientConfiguration.java
│       │                       │   └── RefluxClientImpl.java
│       │                       └── server/
│       │                           ├── ClientAppInfo.java
│       │                           ├── ClientConnectionInfo.java
│       │                           ├── EnableRefluxServer.java
│       │                           ├── RefluxServerConfiguration.java
│       │                           ├── RefluxServerEndpoint.java
│       │                           └── RefluxServerImpl.java
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── commons/
│                               └── reflux/
│                                   ├── Hello.java
│                                   ├── RefluxApplication.java
│                                   ├── SendAndReceiveTest.java
│                                   └── TestServerEndpoint.java
├── commons-restpack/
│   ├── .gitignore
│   ├── README.md
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── restpack/
│       │   │                   ├── EnableRestPack.java
│       │   │                   ├── HttpResult.java
│       │   │                   ├── HttpResultConverter.java
│       │   │                   ├── Log.java
│       │   │                   ├── LogItem.java
│       │   │                   ├── PageResult.java
│       │   │                   ├── RestPackController.java
│       │   │                   ├── RestPackIgnore.java
│       │   │                   ├── ServletUtils.java
│       │   │                   ├── config/
│       │   │                   │   └── RestPackConfiguration.java
│       │   │                   ├── impl/
│       │   │                   │   ├── DateConverter.java
│       │   │                   │   ├── ExceptionHolder.java
│       │   │                   │   ├── HttpAroundHandler.java
│       │   │                   │   ├── HttpErrorHandler.java
│       │   │                   │   ├── HttpResultMapper.java
│       │   │                   │   ├── RestPackAdvice.java
│       │   │                   │   ├── RestPackAspect.java
│       │   │                   │   ├── RestPackConfig.java
│       │   │                   │   ├── RestPackMessageConverter.java
│       │   │                   │   └── RestPackUtils.java
│       │   │                   └── log/
│       │   │                       ├── RestPackLogAppender.java
│       │   │                       └── RestPackLogAspect.java
│       │   └── resources/
│       │       └── restpack/
│       │           └── freemarker.properties
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── terran4j/
│           │           ├── demo/
│           │           │   └── restpack/
│           │           │       ├── DemoHttpResultConverter.java
│           │           │       ├── HelloBean.java
│           │           │       ├── HelloController.java
│           │           │       ├── RestPackDemoApp.java
│           │           │       ├── RestPackDemoAspect.java
│           │           │       ├── RestPackDemoController.java
│           │           │       └── RestPackErrorController.java
│           │           └── test/
│           │               └── restpack/
│           │                   ├── HttpResultConverterTest.java
│           │                   ├── HttpResultMapperTest.java
│           │                   ├── NoHttpResultConverterTest.java
│           │                   └── RestPackTest.java
│           └── resources/
│               ├── application.yml
│               ├── logback.xml
│               ├── static/
│               │   └── restpack/
│               │       └── hello.css
│               └── templates/
│                   └── restpack/
│                       └── hello.ftl
├── commons-test/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── terran4j/
│       │               └── commons/
│       │                   └── test/
│       │                       ├── BaseHttpTest.java
│       │                       ├── BaseSpringBootTest.java
│       │                       ├── BaseTestExecutionListener.java
│       │                       ├── DatabaseInitializer.java
│       │                       ├── DatabaseTestConfig.java
│       │                       ├── ExtAssert.java
│       │                       ├── MockitoInitializer.java
│       │                       ├── RedisTestConfig.java
│       │                       ├── SigListener.java
│       │                       ├── TruncateTable.java
│       │                       ├── database.properties
│       │                       └── redis.properties
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── commons/
│                           └── test/
│                               ├── HelloService.java
│                               ├── MockitoTest.java
│                               └── TestApp.java
├── commons-util/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── com/
│       │       │   └── terran4j/
│       │       │       └── commons/
│       │       │           └── util/
│       │       │               ├── Arrays.java
│       │       │               ├── Beans.java
│       │       │               ├── Checker.java
│       │       │               ├── Classes.java
│       │       │               ├── DateTimes.java
│       │       │               ├── Encoding.java
│       │       │               ├── Enums.java
│       │       │               ├── Expressions.java
│       │       │               ├── Files.java
│       │       │               ├── IOUtils.java
│       │       │               ├── IdWorker.java
│       │       │               ├── Jsons.java
│       │       │               ├── Maths.java
│       │       │               ├── Objects.java
│       │       │               ├── Randoms.java
│       │       │               ├── Server.java
│       │       │               ├── Strings.java
│       │       │               ├── config/
│       │       │               │   ├── ConfigElement.java
│       │       │               │   ├── JsonConfigElement.java
│       │       │               │   └── XmlConfigElement.java
│       │       │               ├── error/
│       │       │               │   ├── AuthorizedException.java
│       │       │               │   ├── BusinessException.java
│       │       │               │   ├── CommonErrorCode.java
│       │       │               │   ├── ErrorCode.java
│       │       │               │   ├── ErrorCodes.java
│       │       │               │   ├── ErrorMessage.java
│       │       │               │   ├── ErrorReport.java
│       │       │               │   ├── ResourceErrorCode.java
│       │       │               │   ├── SimpleErrorCode.java
│       │       │               │   └── null.properties
│       │       │               ├── reflect/
│       │       │               │   └── InterfaceFilter.java
│       │       │               ├── security/
│       │       │               │   ├── AsymmetricKeys.java
│       │       │               │   ├── MD5Util.java
│       │       │               │   └── Security.java
│       │       │               ├── task/
│       │       │               │   └── LoopExecuteTask.java
│       │       │               ├── value/
│       │       │               │   ├── JsonValueSource.java
│       │       │               │   ├── KeyedList.java
│       │       │               │   ├── MapValueSource.java
│       │       │               │   ├── ResourceBundlesProperties.java
│       │       │               │   ├── RichProperties.java
│       │       │               │   ├── ValueSource.java
│       │       │               │   ├── ValueSources.java
│       │       │               │   └── ValueWrapper.java
│       │       │               └── web/
│       │       │                   ├── Cookies.java
│       │       │                   └── IPAddresses.java
│       │       └── error.properties
│       └── test/
│           └── java/
│               ├── com/
│               │   └── terran4j/
│               │       └── common/
│               │           └── util/
│               │               ├── ClassesTest.java
│               │               ├── DateTimesTest.java
│               │               ├── EnumsTest.java
│               │               ├── ExpressionsTest.java
│               │               ├── JsonConfigElementTest.java
│               │               ├── JsonConfigElementTest.json
│               │               ├── JsonsTest.java
│               │               ├── LoopExecuteTaskTest.java
│               │               ├── SecurityTest.java
│               │               ├── StringsTest.java
│               │               ├── ValueTest.java
│               │               └── error/
│               │                   ├── BusinessExceptionTest.java
│               │                   ├── MockErrorCode.java
│               │                   ├── MockException.properties
│               │                   └── testGetReport.txt
│               └── error.properties
├── commons-website/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── terran4j/
│       │   │           └── commons/
│       │   │               └── website/
│       │   │                   ├── config/
│       │   │                   │   ├── Readme.java
│       │   │                   │   └── WebsiteConfiguration.java
│       │   │                   └── controller/
│       │   │                       └── WelcomeController.java
│       │   └── resources/
│       │       └── static/
│       │           └── website/
│       │               ├── flexible-lite/
│       │               │   └── flexible-lite-1.0.js
│       │               ├── less/
│       │               │   └── less-1.7.0.js
│       │               └── vue/
│       │                   └── vue-2.5.10.js
│       └── test/
│           └── java/
│               └── com/
│                   └── terran4j/
│                       └── test/
│                           └── website/
│                               ├── HelloController.java
│                               └── MainApp.java
├── pom.xml
└── version.md
Download .txt
Showing preview only (250K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3080 symbols across 322 files)

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/Api2DocMocker.java
  class Api2DocMocker (line 7) | public class Api2DocMocker {
    method mockBean (line 9) | public static <T> T mockBean(Class<T> clazz) {
    method mockList (line 13) | public static <T> List<T> mockList(Class<T> clazz, int size) {
    method mockArray (line 17) | public static <T> T[] mockArray(Class<T> clazz, int size) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeConfig.java
  class CodeConfig (line 8) | public class CodeConfig {
    method getExtraPrams (line 10) | public List<ApiParamObject> getExtraPrams(ApiDocObject doc) {
    method getPkgName (line 18) | public String getPkgName() {
    method setPkgName (line 22) | public void setPkgName(String pkgName) {
    method getDeclaredComment (line 26) | public String getDeclaredComment() {
    method setDeclaredComment (line 30) | public void setDeclaredComment(String declareComment) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeOutput.java
  type CodeOutput (line 3) | public interface CodeOutput {
    method writeCodeFile (line 5) | void writeCodeFile(String fileName, String fileContent);
    method setPercent (line 7) | void setPercent(int percent);
    method log (line 9) | void log(String log, String... args);

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeUtils.java
  class CodeUtils (line 5) | public class CodeUtils {
    method addImport (line 7) | public static final void addImport(Class<?> clazz, Set<String> imports) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/EnumCodeWriter.java
  class EnumCodeWriter (line 25) | @Service
    method init (line 35) | @PostConstruct
    method writeCode (line 45) | @SuppressWarnings({"rawtypes", "unchecked"})
    class EnumInfo (line 100) | public static final class EnumInfo {
      method getComment (line 106) | public String getComment() {
      method setComment (line 110) | public void setComment(String comment) {
      method getName (line 114) | public String getName() {
      method setName (line 118) | public void setName(String name) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/FileCodeOutput.java
  class FileCodeOutput (line 7) | public class FileCodeOutput implements CodeOutput {
    method FileCodeOutput (line 11) | public FileCodeOutput(String path) {
    method writeCodeFile (line 16) | @Override
    method setPercent (line 22) | @Override
    method log (line 26) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/JavaBeanCodeWriter.java
  class JavaBeanCodeWriter (line 18) | @Service
    method init (line 32) | @PostConstruct
    method writeCode (line 42) | public void writeCode(ApiResultObject result, String className, //
    method getModel (line 57) | public Map<String, Object> getModel(ApiResultObject result, String cla...
    method toGetMethodName (line 113) | private String toGetMethodName(boolean isBooleanClass, String fieldNam...
    method toSetMethodName (line 124) | private String toSetMethodName(String fieldName) {
    method getBaseName (line 130) | private String getBaseName(String name) {
    method getSourceType (line 134) | private Class<?> getSourceType(ApiResultObject result) {
    method toTypeName (line 139) | private String toTypeName(ApiResultObject result) {
    class FieldInfo (line 150) | public static final class FieldInfo {
      method getType (line 162) | public String getType() {
      method setType (line 166) | public void setType(String type) {
      method getName (line 170) | public String getName() {
      method setName (line 174) | public void setName(String name) {
      method getComment (line 178) | public String getComment() {
      method setComment (line 182) | public void setComment(String comment) {
      method getGetMethod (line 186) | public String getGetMethod() {
      method setGetMethod (line 190) | public void setGetMethod(String getMethod) {
      method getSetMethod (line 194) | public String getSetMethod() {
      method setSetMethod (line 198) | public void setSetMethod(String setMethod) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/MemoryCodeOutput.java
  class MemoryCodeOutput (line 6) | public class MemoryCodeOutput implements CodeOutput {
    method writeCodeFile (line 10) | @Override
    method setPercent (line 15) | @Override
    method log (line 19) | @Override
    method getCode (line 23) | public String getCode(String fileName) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/RetrofitCodeWriter.java
  class RetrofitCodeWriter (line 21) | @Service
    method init (line 37) | @PostConstruct
    method writeCode (line 48) | public void writeCode(List<ApiFolderObject> folders, CodeOutput out, C...
    method toRetrofitClassName (line 100) | private String toRetrofitClassName(String id) {
    method toModel (line 110) | private Map<String, Object> toModel(ApiFolderObject folder, CodeConfig...
    method toMethodInfo (line 171) | private MethodInfo toMethodInfo(ApiDocObject doc, CodeConfig config, S...
    method toParam (line 236) | private ParamInfo toParam(ApiParamObject srcParam, ApiDocObject doc, S...
    method toParamAnnoName (line 263) | private String toParamAnnoName(ApiParamLocation location, RequestMetho...
    class ParamInfo (line 284) | public static final class ParamInfo {
      method getId (line 292) | public String getId() {
      method setId (line 296) | public void setId(String id) {
      method getComment (line 300) | public String getComment() {
      method setComment (line 304) | public void setComment(String comment) {
      method getExpression (line 308) | public String getExpression() {
      method setExpression (line 312) | public void setExpression(String expression) {
    class MethodInfo (line 318) | public static final class MethodInfo {
      method getReturnClass (line 330) | public String getReturnClass() {
      method setReturnClass (line 334) | public void setReturnClass(String returnClass) {
      method getParams (line 338) | public List<ParamInfo> getParams() {
      method setParams (line 342) | public void setParams(List<ParamInfo> params) {
      method getAnnos (line 346) | public List<String> getAnnos() {
      method setAnnos (line 350) | public void setAnnos(List<String> annos) {
      method getComment (line 354) | public String getComment() {
      method setComment (line 358) | public void setComment(String comment) {
      method getName (line 362) | public String getName() {
      method setName (line 366) | public void setName(String name) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/config/Api2DocConfiguration.java
  class Api2DocConfiguration (line 15) | @ConditionalOnExpression("${api2doc.enabled:true}")

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/Api2DocController.java
  class Api2DocController (line 21) | @Controller
    method home (line 43) | @RequestMapping(value = "/home.html", method = RequestMethod.GET)
    method getDocPath (line 81) | private String getDocPath(String p) {
    method welcome (line 105) | @RequestMapping(value = "/welcome.html", method = RequestMethod.GET)
    method md (line 114) | @RequestMapping(value = "/md/{folderId}/{docId}.html", method = Reques...
    method api2doc (line 122) | @RequestMapping(value = "/api/{fid}/{id}.html", method = RequestMethod...
    method api2test (line 132) | @RequestMapping(value = "/test/{fid}/{id}.html", method = RequestMetho...
    method md2HtmlPage (line 144) | public String md2HtmlPage(String md, String title,

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiEntry.java
  class ApiEntry (line 3) | public class ApiEntry {
    method getKey (line 9) | public String getKey() {
    method setKey (line 13) | public void setKey(String key) {
    method getValue (line 17) | public String getValue() {
    method setValue (line 21) | public void setValue(String value) {
    method equals (line 25) | @Override
    method hashCode (line 36) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiInfo.java
  class ApiInfo (line 6) | public class ApiInfo {
    method getMethods (line 18) | public String[] getMethods() {
    method setMethods (line 22) | public void setMethods(String[] methods) {
    method getDefaultMethod (line 26) | public String getDefaultMethod() {
    method setDefaultMethod (line 30) | public void setDefaultMethod(String defaultMethod) {
    method getUrl (line 34) | public String getUrl() {
    method setUrl (line 38) | public void setUrl(String url) {
    method getParams (line 42) | public List<ApiEntry> getParams() {
    method setParams (line 46) | public void setParams(List<ApiEntry> params) {
    method getHeaders (line 50) | public List<ApiEntry> getHeaders() {
    method setHeaders (line 54) | public void setHeaders(List<ApiEntry> headers) {
    method equals (line 58) | @Override
    method hashCode (line 74) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiMetaController.java
  class ApiMetaController (line 13) | @RestPackController
    method getClassMetaList (line 20) | @RequestMapping(value = "/classes", method = RequestMethod.GET)
    method getApiInfo (line 25) | @RequestMapping(value = "/apiInfo/{fid}/{id}", method = RequestMethod....

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/MenuData.java
  class MenuData (line 8) | public class MenuData implements Comparable<MenuData>{
    method getOrder (line 24) | public int getOrder() {
    method setOrder (line 28) | public void setOrder(int order) {
    method isFolder (line 32) | public final boolean isFolder() {
    method setFolder (line 36) | public final void setFolder(boolean folder) {
    method getId (line 40) | public final String getId() {
    method setId (line 44) | public final void setId(String id) {
    method getIndex (line 48) | public final String getIndex() {
    method setIndex (line 52) | public final void setIndex(String index) {
    method getName (line 56) | public final String getName() {
    method setName (line 60) | public final void setName(String name) {
    method getChildren (line 64) | public final List<MenuData> getChildren() {
    method setChildren (line 68) | public final void setChildren(List<MenuData> children) {
    method getUrl (line 72) | public final String getUrl() {
    method setUrl (line 76) | public final void setUrl(String url) {
    method toString (line 80) | public final String toString() {
    method compareTo (line 84) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDataType.java
  type ApiDataType (line 13) | public enum ApiDataType {
    method getDefault (line 16) | @Override
    method parseValue (line 21) | @Override
    method isSimpleType (line 26) | @Override
    method isArrayType (line 31) | @Override
    method isObjectType (line 36) | @Override
    method getDefault (line 43) | @Override
    method parseValue (line 48) | @Override
    method isSimpleType (line 53) | @Override
    method isArrayType (line 58) | @Override
    method isObjectType (line 63) | @Override
    method getDefault (line 70) | @Override
    method parseValue (line 75) | @Override
    method isSimpleType (line 80) | @Override
    method isArrayType (line 85) | @Override
    method isObjectType (line 90) | @Override
    method getDefault (line 97) | @Override
    method parseValue (line 102) | @Override
    method isSimpleType (line 107) | @Override
    method isArrayType (line 112) | @Override
    method isObjectType (line 117) | @Override
    method getDefault (line 124) | @Override
    method parseValue (line 129) | @Override
    method isSimpleType (line 134) | @Override
    method isArrayType (line 139) | @Override
    method isObjectType (line 144) | @Override
    method getDefault (line 151) | @Override
    method parseValue (line 156) | @Override
    method isSimpleType (line 161) | @Override
    method isArrayType (line 166) | @Override
    method isObjectType (line 171) | @Override
    method getDefault (line 178) | @Override
    method parseValue (line 183) | @Override
    method isSimpleType (line 188) | @Override
    method isArrayType (line 193) | @Override
    method isObjectType (line 198) | @Override
    method ApiDataType (line 206) | ApiDataType(String name) {
    method getName (line 210) | public String getName() {
    method getDefault (line 214) | public abstract String getDefault();
    method parseValue (line 216) | public abstract Object parseValue(String text);
    method isSimpleType (line 218) | public abstract boolean isSimpleType();
    method isArrayType (line 220) | public abstract boolean isArrayType();
    method isObjectType (line 222) | public abstract boolean isObjectType();
    method getJsonSchemaGenerator (line 226) | public static final JsonSchemaGenerator getJsonSchemaGenerator() {
    method toDataType (line 243) | public static ApiDataType toDataType(Class<?> clazz) {
    method toDataType (line 260) | public static ApiDataType toDataType(JsonSchema schema) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocObject.java
  class ApiDocObject (line 10) | public class ApiDocObject extends ApiObject {
    method getResultType (line 30) | public ApiResultObject getResultType() {
    method setResultType (line 34) | public void setResultType(ApiResultObject resultType) {
    method getSourceMethod (line 38) | public Method getSourceMethod() {
    method setSourceMethod (line 42) | public void setSourceMethod(Method sourceMethod) {
    method getPaths (line 46) | public String[] getPaths() {
    method setPaths (line 50) | public void setPaths(String[] paths) {
    method getMethods (line 54) | public RequestMethod[] getMethods() {
    method setMethods (line 58) | public void setMethods(RequestMethod[] methods) {
    method getParams (line 62) | public final List<ApiParamObject> getParams() {
    method getParam (line 66) | public final ApiParamObject getParam(String id) {
    method addParam (line 70) | public final void addParam(ApiParamObject param) {
    method getResults (line 74) | public List<ApiResultObject> getResults() {
    method setResults (line 78) | public void setResults(List<ApiResultObject> results) {
    method getErrors (line 82) | public List<ApiErrorObject> getErrors() {
    method addError (line 86) | public void addError(ApiErrorObject error) {
    method getFolder (line 90) | public ApiFolderObject getFolder() {
    method setFolder (line 94) | public void setFolder(ApiFolderObject folder) {
    method getReturnTypeDesc (line 98) | public String getReturnTypeDesc() {
    method setReturnTypeDesc (line 102) | public void setReturnTypeDesc(String returnTypeDesc) {
    method toMockResult (line 106) | public final Object toMockResult() {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocUtils.java
  class ApiDocUtils (line 7) | public class ApiDocUtils {
    method getId (line 9) | public static final String getId(Class<?> clazz) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiErrorObject.java
  class ApiErrorObject (line 3) | public class ApiErrorObject extends ApiObject {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiFolderObject.java
  class ApiFolderObject (line 9) | public class ApiFolderObject extends ApiObject {
    method isRestPack (line 19) | public boolean isRestPack() {
    method setRestPack (line 23) | public void setRestPack(boolean restPack) {
    method getMds (line 27) | public Map<String, String> getMds() {
    method setMds (line 31) | public void setMds(Map<String, String> mds) {
    method getSourceClass (line 35) | public Class<?> getSourceClass() {
    method setSourceClass (line 39) | public void setSourceClass(Class<?> sourceClass) {
    method getDocs (line 43) | public final List<ApiDocObject> getDocs() {
    method getDoc (line 47) | public final ApiDocObject getDoc(String id) {
    method addDocs (line 51) | public final void addDocs(List<ApiDocObject> docList) {
    method addDoc (line 60) | public final void addDoc(ApiDocObject doc) {
    method name2Id (line 72) | public static final String name2Id(String name) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiObject.java
  class ApiObject (line 7) | public class ApiObject implements Comparable<ApiObject>{
    method getId (line 19) | public String getId() {
    method setId (line 23) | public void setId(String id) {
    method getName (line 27) | public String getName() {
    method setName (line 31) | public void setName(String name) {
    method getOrder (line 35) | public final int getOrder() {
    method setOrder (line 39) | public final void setOrder(int order) {
    method insertComment (line 43) | public void insertComment(String comment) {
    method getComment (line 47) | public FlexibleString getComment() {
    method setComment (line 51) | public void setComment(String comment) {
    method getSample (line 55) | public FlexibleString getSample() {
    method setSample (line 59) | public void setSample(String sample) {
    method toString (line 63) | @Override
    method compareTo (line 68) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamLocation.java
  type ApiParamLocation (line 13) | public enum ApiParamLocation {
    method doCollect (line 16) | @Override
    method doCollect (line 48) | @Override
    method doCollect (line 80) | @Override
    method doCollect (line 104) | @Override
    method doCollect (line 136) | @Override
    method doCollect (line 163) | abstract boolean doCollect(ApiParamObject apiParamObject, AnnotatedEle...
    method collects (line 165) | public static final void collects(ApiParamObject apiParamObject, Annot...

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamObject.java
  class ApiParamObject (line 3) | public class ApiParamObject extends ApiObject {
    method ApiParamObject (line 13) | public ApiParamObject() {
    method getSourceType (line 18) | public Class<?> getSourceType() {
    method setSourceType (line 22) | public void setSourceType(Class<?> sourceType) {
    method getTypeName (line 26) | public String getTypeName() {
    method getDataType (line 36) | public ApiDataType getDataType() {
    method setDataType (line 40) | public void setDataType(ApiDataType type) {
    method isRequired (line 44) | public boolean isRequired() {
    method setRequired (line 48) | public void setRequired(boolean required) {
    method getRequiredName (line 52) | public final String getRequiredName() {
    method getLocation (line 56) | public ApiParamLocation getLocation() {
    method setLocation (line 60) | public void setLocation(ApiParamLocation location) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiResultObject.java
  class ApiResultObject (line 25) | public class ApiResultObject extends ApiObject {
    method getSourceType (line 47) | public Class<?> getSourceType() {
    method setSourceType (line 51) | public void setSourceType(Class<?> sourceType) {
    method getRefGroupId (line 55) | public String getRefGroupId() {
    method setRefGroupId (line 59) | public void setRefGroupId(String refGroupId) {
    method getDataType (line 63) | public final ApiDataType getDataType() {
    method setDataType (line 67) | public final void setDataType(ApiDataType dataType) {
    method getTypeName (line 71) | public String getTypeName() {
    method setTypeName (line 75) | public void setTypeName(String typeName) {
    method getChildren (line 79) | public final List<ApiResultObject> getChildren() {
    method getChild (line 83) | public final ApiResultObject getChild(String fieldName) {
    method addChild (line 97) | public final void addChild(ApiResultObject child) {
    method getGroupId (line 101) | public String getGroupId() {
    method setGroupId (line 105) | public void setGroupId(String groupId) {
    method getGroupName (line 109) | public String getGroupName() {
    method setGroupName (line 113) | public void setGroupName(String groupName) {
    method getEnumComment (line 117) | @SuppressWarnings({"unchecked", "rawtypes"})
    method getTypeName (line 154) | private static final String getTypeName(Class<?> clazz, ApiDataType da...
    method parseResultType (line 171) | public static final ApiResultObject parseResultType(
    method getGroupId (line 344) | public static final String getGroupId(Class<?> clazz) {
    method createSimple (line 352) | private static ApiResultObject createSimple(Class<?> sourceType,

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/DateConverter.java
  class DateConverter (line 5) | public class DateConverter {
    method isDateType (line 7) | public static boolean isDateType(Class<?> clazz) {
    method dateAsLongValue (line 11) | public static Object dateAsLongValue(Class<?> clazz) {
    method dateAsLongType (line 19) | public static ApiDataType dateAsLongType(Class<?> clazz) {
    method dateAsLongClass (line 26) | public static Class<?> dateAsLongClass(Class<?> clazz) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocCollector.java
  class Api2DocCollector (line 36) | @Service
    method postProcessAfterInitialization (line 47) | @Override
    method postProcessBeforeInitialization (line 74) | @Override
    method toApiFolder (line 87) | public ApiFolderObject toApiFolder(Object bean, String beanName) throw...
    method getApiDoc (line 233) | ApiDocObject getApiDoc(
    method toApiParams (line 357) | public List<ApiParamObject> toApiParams(Method method, Class<?> defaul...
    method toApiParams (line 416) | public List<ApiParamObject> toApiParams(Class<?> beanClass, Class<?> d...
    method getError (line 456) | ApiErrorObject getError(ApiError errorCode) {
    method toApiParam (line 479) | ApiParamObject toApiParam(
    method combine (line 509) | String[] combine(String[] classPaths, String[] methodPaths) {
    method convertType (line 527) | ApiDataType convertType(Class<?> paramType) {
    method getPath (line 572) | private String[] getPath(RequestMapping mapping) {
    method checkId (line 591) | private void checkId(String id) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocObjectFactory.java
  class Api2DocObjectFactory (line 21) | public class Api2DocObjectFactory {
    method createObject (line 25) | public static Object createObject(ApiDataType dataType,
    method createBean (line 44) | public static <T> T createBean(Class<T> clazz) {
    method createList (line 49) | public static <E> List<E> createList(Class<E> clazz, int size) {
    method createArray (line 54) | public static <T> T[] createArray(Class<T> clazz, int size) {
    method doCreateList (line 59) | private static <E> List<E> doCreateList(Class<E> clazz, int size, Stac...
    method doCreateArray (line 73) | private static <T> T[] doCreateArray(Class<T> clazz, int size, Stack<C...
    method createBean (line 99) | private static <T> T createBean(Class<T> clazz, String defaultValue, S...
    method fillField (line 174) | private static void fillField(String name, Object bean, Stack<Class<?>...
    method getArraySize (line 267) | private static int getArraySize(String sizeText, int defaultValue) {
    method adaptSimpleType (line 280) | private static Object adaptSimpleType(Object sourceValue, Class<?> tar...
    method getArrayElementClass (line 304) | private static final Class<?> getArrayElementClass(Field field) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocProperties.java
  class Api2DocProperties (line 6) | @Service
    method getServerURL (line 24) | public String getServerURL() {
    method isShowCurl (line 28) | public boolean isShowCurl() {
    method getServiceName (line 32) | public String getServiceName() {
    method getApi2docTitle (line 36) | public String getApi2docTitle() {
    method getApi2docIcon (line 40) | public String getApi2docIcon() {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocService.java
  class Api2DocService (line 12) | @Service
    method hasFolder (line 21) | public boolean hasFolder(String id) {
    method getFolder (line 25) | public ApiFolderObject getFolder(String id) {
    method addFolder (line 29) | public void addFolder(ApiFolderObject folder) {
    method getFolders (line 36) | public List<ApiFolderObject> getFolders() {
    method addAppDocVersion (line 40) | public String addAppDocVersion(String path) {
    method getAppDocVersion (line 48) | public String getAppDocVersion() {
    method getComponentVersion (line 52) | public String getComponentVersion() {
    method getDocObject (line 56) | public ApiDocObject getDocObject(String folderId, String docId) throws...

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocUtils.java
  class Api2DocUtils (line 27) | public class Api2DocUtils {
    method toURL (line 29) | public static String toURL(ApiDocObject doc, String serverURL) {
    method encode (line 112) | private static String encode(String text) {
    method getArrayElementClass (line 162) | public static final Class<?> getArrayElementClass(Method method) {
    method getGenericType (line 182) | public static final Type getGenericType(Type gType) {
    method isFilter (line 195) | public static final boolean isFilter(

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ApiCommentUtils.java
  class ApiCommentUtils (line 13) | public class ApiCommentUtils {
    method getDefaultSeeClass (line 16) | public static Class<?> getDefaultSeeClass(ApiComment apiComment,
    method setApiComment (line 30) | public static final void setApiComment(ApiComment apiComment,
    method getComment (line 47) | public static final String getComment(ApiComment apiComment,
    method getSample (line 71) | public static final String getSample(ApiComment apiComment,
    method getSeeApiComment (line 101) | private static ApiComment getSeeApiComment(

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ClasspathFreeMarker.java
  class ClasspathFreeMarker (line 18) | @Service
    method ClasspathFreeMarker (line 25) | public ClasspathFreeMarker() {
    method getPath (line 38) | private String getPath(Class<?> clazz, String fileName) {
    method getTemplate (line 43) | public final Template getTemplate(Class<?> clazz, String fileName) {
    method build (line 67) | public final String build(Template template, Map<String, Object> model...

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/CurlBuilder.java
  class CurlBuilder (line 23) | public class CurlBuilder {
    method toCurl (line 29) | public static String toCurl(ApiDocObject docObject, String serverURL) {
    method joinText (line 150) | public static final String joinText(KeyedList<String, String> params,
    method encode (line 167) | private static String encode(String value) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocMenuBuilder.java
  class DocMenuBuilder (line 16) | @Service
    method getMenuGroups (line 22) | public List<MenuData> getMenuGroups() {
    method getMenuGroup (line 40) | public MenuData getMenuGroup(ApiFolderObject folder) {
    method getMenu (line 74) | public MenuData getMenu(String mdFileName, String folderId) {
    method getMenu (line 96) | public MenuData getMenu(ApiDocObject doc, String folderId) {
    method getPageURL (line 112) | private String getPageURL(String pageId) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocPageBuilder.java
  class DocPageBuilder (line 30) | @Service
    method init (line 52) | @PostConstruct
    method md2Html (line 87) | public String md2Html(String md) throws Exception {
    method doc2Md (line 125) | public String doc2Md(ApiDocObject doc) {
    method loadMdFromResource (line 171) | public String loadMdFromResource(String path) throws Exception {
    method loadMdFromResource (line 186) | public String loadMdFromResource(String folderId, String docId) throws...

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/FlexibleString.java
  class FlexibleString (line 7) | public class FlexibleString {
    method FlexibleString (line 11) | public FlexibleString() {
    method FlexibleString (line 14) | public FlexibleString(String value) {
    method getValue (line 20) | public String getValue() {
    method setValue (line 27) | public void setValue(String value) {
    method append (line 35) | public FlexibleString append(String appendValue) {
    method insertLine (line 42) | public FlexibleString insertLine(String insertValue) {
    method html (line 53) | public String html() {
    method javadoc (line 61) | public String javadoc(int indent) {
    method toString (line 73) | @Override

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/MappingMethod.java
  class MappingMethod (line 9) | public class MappingMethod {
    method MappingMethod (line 22) | private MappingMethod(Method method) {
    method getMethod (line 26) | public Method getMethod() {
    method getName (line 30) | public String getName() {
    method getRequestMethod (line 64) | RequestMethod[] getRequestMethod() {
    method getPath (line 102) | public String[] getPath() {
    method merge (line 136) | private String[] merge(String[] strs1, String[] strs2) {
    method getMappingMethods (line 150) | public static List<MappingMethod> getMappingMethods(Class<?> clazz) {
    method isMappingMethod (line 168) | public static boolean isMappingMethod(Method method) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ApiMetaService.java
  class ApiMetaService (line 17) | @Service
    method toApiInfo (line 23) | public ApiInfo toApiInfo(String folderId, String docId) throws Excepti...
    method toClassMetaList (line 51) | public List<ClassMeta> toClassMetaList() {
    method toClassMeta (line 66) | public ClassMeta toClassMeta(ApiFolderObject folder) {
    method toMethodMeta (line 83) | public MethodMeta toMethodMeta(ApiDocObject doc) {
    method toParamMeta (line 102) | public ParamMeta toParamMeta(ApiParamObject param) {
    method toRequestMethods (line 113) | private String[] toRequestMethods(RequestMethod[] methods) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ClassMeta.java
  class ClassMeta (line 6) | public class ClassMeta {
    method getId (line 16) | public String getId() {
    method setId (line 20) | public void setId(String id) {
    method getName (line 24) | public String getName() {
    method setName (line 28) | public void setName(String name) {
    method getComment (line 32) | public String getComment() {
    method setComment (line 36) | public void setComment(String comment) {
    method getMethods (line 40) | public List<MethodMeta> getMethods() {
    method addMethod (line 44) | public void addMethod(MethodMeta method) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/MethodMeta.java
  class MethodMeta (line 6) | public class MethodMeta {
    method getId (line 20) | public String getId() {
    method setId (line 24) | public void setId(String id) {
    method getName (line 28) | public String getName() {
    method setName (line 32) | public void setName(String name) {
    method getComment (line 36) | public String getComment() {
    method setComment (line 40) | public void setComment(String comment) {
    method getPaths (line 44) | public String[] getPaths() {
    method setPaths (line 48) | public void setPaths(String[] paths) {
    method getRequestMethods (line 52) | public String[] getRequestMethods() {
    method setRequestMethods (line 56) | public void setRequestMethods(String[] requestMethods) {
    method getParams (line 60) | public List<ParamMeta> getParams() {
    method addParam (line 64) | public void addParam(ParamMeta param) {

FILE: commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ParamMeta.java
  class ParamMeta (line 6) | public class ParamMeta {
    method getId (line 20) | public String getId() {
    method setId (line 24) | public void setId(String id) {
    method getName (line 28) | public String getName() {
    method setName (line 32) | public void setName(String name) {
    method getComment (line 36) | public String getComment() {
    method setComment (line 40) | public void setComment(String comment) {
    method isRequired (line 44) | public boolean isRequired() {
    method setRequired (line 48) | public void setRequired(boolean required) {
    method getDataType (line 52) | public String getDataType() {
    method setDataType (line 56) | public void setDataType(String dataType) {
    method getLocation (line 60) | public String getLocation() {
    method setLocation (line 64) | public void setLocation(String location) {

FILE: commons-api2doc/src/main/resources/static/api2doc/flexible-lite/flexible-lite-1.0.js
  function flex (line 4) | function flex(designWidth) {

FILE: commons-api2doc/src/main/resources/static/api2doc/less/less-1.7.0.js
  function require (line 18) | function require(arg) {
  function save (line 140) | function save()    { currentPos = i; saveStack.push( { current: current,...
  function restore (line 141) | function restore() { var state = saveStack.pop(); current = state.curren...
  function forget (line 142) | function forget() { saveStack.pop(); }
  function sync (line 144) | function sync() {
  function isWhitespace (line 150) | function isWhitespace(str, pos) {
  function $ (line 157) | function $(tok) {
  function $re (line 195) | function $re(tok) {
  function $char (line 216) | function $char(tok) {
  function skipWhitespace (line 224) | function skipWhitespace(length) {
  function expect (line 255) | function expect(arg, msg) {
  function expectChar (line 266) | function expectChar(arg, msg) {
  function error (line 274) | function error(msg, type) {
  function peek (line 283) | function peek(tok) {
  function peekChar (line 292) | function peekChar(tok) {
  function getInput (line 297) | function getInput(e, env) {
  function getLocation (line 305) | function getLocation(index, inputStream) {
  function getDebugInfo (line 324) | function getDebugInfo(index, inputStream, env) {
  function LessError (line 336) | function LessError(e, env) {
  function fail (line 408) | function fail(msg, index) {
  function emitChunk (line 417) | function emitChunk(force) {
  function match (line 2049) | function match(re) {
  function hue (line 2112) | function hue(h) {
  function throwArgumentDescriptor (line 2575) | function throwArgumentDescriptor() {
  function _math (line 2694) | function _math(fn, unit, n) {
  function colorBlend (line 2711) | function colorBlend(mode, color1, color2) {
  function initFunctions (line 2795) | function initFunctions() {
  function hsla (line 2818) | function hsla(color) {
  function scaled (line 2822) | function scaled(n, size) {
  function number (line 2830) | function number(n) {
  function clamp (line 2843) | function clamp(val) {
  function toHex (line 3460) | function toHex(v) {
  function clamp (line 3467) | function clamp(v, max) {
  function evalName (line 5105) | function evalName(env, name) {
  function _noop (line 6110) | function _noop(node) {
  function indexNodeTypes (line 6114) | function indexNodeTypes(parent, ticker) {
  function toExpression (line 6642) | function toExpression(values) {
  function toValue (line 6648) | function toValue(values) {
  function log (line 7296) | function log(str, level) {
  function extractId (line 7302) | function extractId(href) {
  function errorConsole (line 7310) | function errorConsole(e, rootHref) {
  function createCSS (line 7337) | function createCSS(styles, sheet, lastModified) {
  function postProcessCSS (line 7399) | function postProcessCSS(styles) {
  function errorHTML (line 7406) | function errorHTML(e, rootHref) {
  function error (line 7504) | function error(e, rootHref) {
  function removeErrorHTML (line 7514) | function removeErrorHTML(path) {
  function removeErrorConsole (line 7521) | function removeErrorConsole(path) {
  function removeError (line 7525) | function removeError(path) {
  function loadStyles (line 7535) | function loadStyles(modifyVars) {
  function extractUrlParts (line 7570) | function extractUrlParts(url, baseUrl) {
  function pathDiff (line 7624) | function pathDiff(url, baseUrl) {
  function getXMLHttpRequest (line 7648) | function getXMLHttpRequest() {
  function doXHR (line 7662) | function doXHR(url, type, callback, errback) {
  function loadFile (line 7700) | function loadFile(originalHref, currentFileInfo, callback, env, modifyVa...
  function loadStyleSheet (line 7760) | function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
  function loadStyleSheets (line 7807) | function loadStyleSheets(callback, reload, modifyVars) {
  function initRunningMode (line 7813) | function initRunningMode(){

FILE: commons-api2doc/src/main/resources/static/api2doc/vue/vue-2.5.10.js
  function isUndef (line 18) | function isUndef (v) {
  function isDef (line 22) | function isDef (v) {
  function isTrue (line 26) | function isTrue (v) {
  function isFalse (line 30) | function isFalse (v) {
  function isPrimitive (line 37) | function isPrimitive (value) {
  function isObject (line 50) | function isObject (obj) {
  function toRawType (line 59) | function toRawType (value) {
  function isPlainObject (line 67) | function isPlainObject (obj) {
  function isRegExp (line 71) | function isRegExp (v) {
  function isValidArrayIndex (line 78) | function isValidArrayIndex (val) {
  function toString (line 86) | function toString (val) {
  function toNumber (line 98) | function toNumber (val) {
  function makeMap (line 107) | function makeMap (
  function remove (line 134) | function remove (arr, item) {
  function hasOwn (line 147) | function hasOwn (obj, key) {
  function cached (line 154) | function cached (fn) {
  function bind (line 188) | function bind (fn, ctx) {
  function toArray (line 205) | function toArray (list, start) {
  function extend (line 218) | function extend (to, _from) {
  function toObject (line 228) | function toObject (arr) {
  function noop (line 243) | function noop (a, b, c) {}
  function genStaticKeys (line 258) | function genStaticKeys (modules) {
  function looseEqual (line 268) | function looseEqual (a, b) {
  function looseIndexOf (line 301) | function looseIndexOf (arr, val) {
  function once (line 311) | function once (fn) {
  function isReserved (line 436) | function isReserved (str) {
  function def (line 444) | function def (obj, key, val, enumerable) {
  function parsePath (line 457) | function parsePath (path) {
  function isNative (line 527) | function isNative (Ctor) {
  function Set (line 543) | function Set () {
  function pushTarget (line 696) | function pushTarget (_target) {
  function popTarget (line 701) | function popTarget () {
  function createTextVNode (line 761) | function createTextVNode (val) {
  function cloneVNode (line 769) | function cloneVNode (vnode, deep) {
  function cloneVNodes (line 800) | function cloneVNodes (vnodes, deep) {
  function protoAugment (line 913) | function protoAugment (target, src, keys) {
  function copyAugment (line 924) | function copyAugment (target, src, keys) {
  function observe (line 936) | function observe (value, asRootData) {
  function defineReactive (line 961) | function defineReactive (
  function set (line 1022) | function set (target, key, val) {
  function del (line 1052) | function del (target, key) {
  function dependArray (line 1079) | function dependArray (value) {
  function mergeData (line 1116) | function mergeData (to, from) {
  function mergeDataOrFn (line 1136) | function mergeDataOrFn (
  function mergeHook (line 1203) | function mergeHook (
  function mergeAssets (line 1227) | function mergeAssets (
  function checkComponents (line 1317) | function checkComponents (options) {
  function validateComponentName (line 1323) | function validateComponentName (name) {
  function normalizeProps (line 1344) | function normalizeProps (options, vm) {
  function normalizeInject (line 1381) | function normalizeInject (options, vm) {
  function normalizeDirectives (line 1407) | function normalizeDirectives (options) {
  function assertObjectType (line 1419) | function assertObjectType (name, value, vm) {
  function mergeOptions (line 1433) | function mergeOptions (
  function resolveAsset (line 1480) | function resolveAsset (
  function validateProp (line 1510) | function validateProp (
  function getPropDefaultValue (line 1546) | function getPropDefaultValue (vm, prop, key) {
  function assertProp (line 1579) | function assertProp (
  function assertType (line 1631) | function assertType (value, type) {
  function getType (line 1659) | function getType (fn) {
  function isType (line 1664) | function isType (type, fn) {
  function handleError (line 1679) | function handleError (err, vm, info) {
  function globalHandleError (line 1699) | function globalHandleError (err, vm, info) {
  function logError (line 1710) | function logError (err, vm, info) {
  function flushCallbacks (line 1728) | function flushCallbacks () {
  function withMacroTask (line 1798) | function withMacroTask (fn) {
  function nextTick (line 1807) | function nextTick (cb, ctx) {
  function traverse (line 1946) | function traverse (val) {
  function _traverse (line 1951) | function _traverse (val, seen) {
  function createFnInvoker (line 1991) | function createFnInvoker (fns) {
  function updateListeners (line 2010) | function updateListeners (
  function mergeVNodeHook (line 2047) | function mergeVNodeHook (def, hookKey, hook) {
  function extractPropsFromVNodeData (line 2082) | function extractPropsFromVNodeData (
  function checkProp (line 2123) | function checkProp (
  function simpleNormalizeChildren (line 2162) | function simpleNormalizeChildren (children) {
  function normalizeChildren (line 2175) | function normalizeChildren (children) {
  function isTextNode (line 2183) | function isTextNode (node) {
  function normalizeArrayChildren (line 2187) | function normalizeArrayChildren (children, nestedIndex) {
  function ensureCtor (line 2237) | function ensureCtor (comp, base) {
  function createAsyncPlaceholder (line 2249) | function createAsyncPlaceholder (
  function resolveAsyncComponent (line 2262) | function resolveAsyncComponent (
  function isAsyncPlaceholder (line 2364) | function isAsyncPlaceholder (node) {
  function getFirstComponentChild (line 2370) | function getFirstComponentChild (children) {
  function initEvents (line 2385) | function initEvents (vm) {
  function add (line 2397) | function add (event, fn, once) {
  function remove$1 (line 2405) | function remove$1 (event, fn) {
  function updateComponentListeners (line 2409) | function updateComponentListeners (
  function eventsMixin (line 2419) | function eventsMixin (Vue) {
  function resolveSlots (line 2526) | function resolveSlots (
  function isWhitespace (line 2566) | function isWhitespace (node) {
  function resolveScopedSlots (line 2570) | function resolveScopedSlots (
  function initLifecycle (line 2590) | function initLifecycle (vm) {
  function lifecycleMixin (line 2616) | function lifecycleMixin (Vue) {
  function mountComponent (line 2710) | function mountComponent (
  function updateChildComponent (line 2778) | function updateChildComponent (
  function isInInactiveTree (line 2843) | function isInInactiveTree (vm) {
  function activateChildComponent (line 2850) | function activateChildComponent (vm, direct) {
  function deactivateChildComponent (line 2868) | function deactivateChildComponent (vm, direct) {
  function callHook (line 2884) | function callHook (vm, hook) {
  function resetSchedulerState (line 2916) | function resetSchedulerState () {
  function flushSchedulerQueue (line 2928) | function flushSchedulerQueue () {
  function callUpdatedHooks (line 2983) | function callUpdatedHooks (queue) {
  function queueActivatedComponent (line 2998) | function queueActivatedComponent (vm) {
  function callActivatedHooks (line 3005) | function callActivatedHooks (queue) {
  function queueWatcher (line 3017) | function queueWatcher (watcher) {
  function proxy (line 3260) | function proxy (target, sourceKey, key) {
  function initState (line 3270) | function initState (vm) {
  function initProps (line 3286) | function initProps (vm, propsOptions) {
  function initData (line 3332) | function initData (vm) {
  function getData (line 3374) | function getData (data, vm) {
  function initComputed (line 3385) | function initComputed (vm, computed) {
  function defineComputed (line 3425) | function defineComputed (
  function createComputedGetter (line 3458) | function createComputedGetter (key) {
  function initMethods (line 3473) | function initMethods (vm, methods) {
  function initWatch (line 3501) | function initWatch (vm, watch) {
  function createWatcher (line 3514) | function createWatcher (
  function stateMixin (line 3530) | function stateMixin (Vue) {
  function initProvide (line 3579) | function initProvide (vm) {
  function initInjections (line 3588) | function initInjections (vm) {
  function resolveInject (line 3609) | function resolveInject (inject, vm) {
  function renderList (line 3651) | function renderList (
  function renderSlot (line 3685) | function renderSlot (
  function resolveFilter (line 3734) | function resolveFilter (id) {
  function checkKeyCodes (line 3745) | function checkKeyCodes (
  function bindObjectProps (line 3768) | function bindObjectProps (
  function renderStatic (line 3822) | function renderStatic (
  function markOnce (line 3849) | function markOnce (
  function markStatic (line 3858) | function markStatic (
  function markStaticNode (line 3874) | function markStaticNode (node, key, isOnce) {
  function bindObjectListeners (line 3882) | function bindObjectListeners (data, value) {
  function installRenderHelpers (line 3903) | function installRenderHelpers (target) {
  function FunctionalRenderContext (line 3923) | function FunctionalRenderContext (
  function createFunctionalComponent (line 3970) | function createFunctionalComponent (
  function mergeProps (line 4010) | function mergeProps (to, from) {
  function createComponent (line 4088) | function createComponent (
  function createComponentInstanceForVnode (line 4186) | function createComponentInstanceForVnode (
  function mergeHooks (line 4208) | function mergeHooks (data) {
  function mergeHook$1 (line 4220) | function mergeHook$1 (one, two) {
  function transformModel (line 4229) | function transformModel (options, data) {
  function createElement (line 4247) | function createElement (
  function _createElement (line 4266) | function _createElement (
  function applyNS (line 4346) | function applyNS (vnode, ns, force) {
  function initRender (line 4365) | function initRender (vm) {
  function renderMixin (line 4397) | function renderMixin (Vue) {
  function initMixin (line 4472) | function initMixin (Vue) {
  function initInternalComponent (line 4529) | function initInternalComponent (vm, options) {
  function resolveConstructorOptions (line 4550) | function resolveConstructorOptions (Ctor) {
  function resolveModifiedOptions (line 4574) | function resolveModifiedOptions (Ctor) {
  function dedupe (line 4588) | function dedupe (latest, extended, sealed) {
  function Vue$3 (line 4607) | function Vue$3 (options) {
  function initUse (line 4624) | function initUse (Vue) {
  function initMixin$1 (line 4646) | function initMixin$1 (Vue) {
  function initExtend (line 4655) | function initExtend (Vue) {
  function initProps$1 (line 4731) | function initProps$1 (Comp) {
  function initComputed$1 (line 4738) | function initComputed$1 (Comp) {
  function initAssetRegisters (line 4747) | function initAssetRegisters (Vue) {
  function getComponentName (line 4779) | function getComponentName (opts) {
  function matches (line 4783) | function matches (pattern, name) {
  function pruneCache (line 4795) | function pruneCache (keepAliveInstance, filter) {
  function pruneCacheEntry (line 4810) | function pruneCacheEntry (
  function initGlobalAPI (line 4911) | function initGlobalAPI (Vue) {
  function genClassForVnode (line 5014) | function genClassForVnode (vnode) {
  function mergeClassData (line 5032) | function mergeClassData (child, parent) {
  function renderClass (line 5041) | function renderClass (
  function concat (line 5052) | function concat (a, b) {
  function stringifyClass (line 5056) | function stringifyClass (value) {
  function stringifyArray (line 5070) | function stringifyArray (value) {
  function stringifyObject (line 5082) | function stringifyObject (value) {
  function getTagNamespace (line 5129) | function getTagNamespace (tag) {
  function isUnknownElement (line 5141) | function isUnknownElement (tag) {
  function query (line 5173) | function query (el) {
  function createElement$1 (line 5190) | function createElement$1 (tagName, vnode) {
  function createElementNS (line 5202) | function createElementNS (namespace, tagName) {
  function createTextNode (line 5206) | function createTextNode (text) {
  function createComment (line 5210) | function createComment (text) {
  function insertBefore (line 5214) | function insertBefore (parentNode, newNode, referenceNode) {
  function removeChild (line 5218) | function removeChild (node, child) {
  function appendChild (line 5222) | function appendChild (node, child) {
  function parentNode (line 5226) | function parentNode (node) {
  function nextSibling (line 5230) | function nextSibling (node) {
  function tagName (line 5234) | function tagName (node) {
  function setTextContent (line 5238) | function setTextContent (node, text) {
  function setAttribute (line 5242) | function setAttribute (node, key, val) {
  function registerRef (line 5279) | function registerRef (vnode, isRemoval) {
  function sameVnode (line 5322) | function sameVnode (a, b) {
  function sameInputType (line 5339) | function sameInputType (a, b) {
  function createKeyToOldIdx (line 5347) | function createKeyToOldIdx (children, beginIdx, endIdx) {
  function createPatchFunction (line 5357) | function createPatchFunction (backend) {
  function updateDirectives (line 6052) | function updateDirectives (oldVnode, vnode) {
  function _update (line 6058) | function _update (oldVnode, vnode) {
  function normalizeDirectives$1 (line 6120) | function normalizeDirectives$1 (
  function getRawDirName (line 6140) | function getRawDirName (dir) {
  function callHook$1 (line 6144) | function callHook$1 (dir, hook, vnode, oldVnode, isDestroy) {
  function updateAttrs (line 6162) | function updateAttrs (oldVnode, vnode) {
  function setAttr (line 6203) | function setAttr (el, key, value) {
  function updateClass (line 6258) | function updateClass (oldVnode, vnode) {
  function parseFilters (line 6298) | function parseFilters (exp) {
  function wrapFilter (line 6380) | function wrapFilter (exp, filter) {
  function baseWarn (line 6394) | function baseWarn (msg) {
  function pluckModuleFunction (line 6398) | function pluckModuleFunction (
  function addProp (line 6407) | function addProp (el, name, value) {
  function addAttr (line 6411) | function addAttr (el, name, value) {
  function addDirective (line 6415) | function addDirective (
  function addHandler (line 6426) | function addHandler (
  function getBindingAttr (line 6498) | function getBindingAttr (
  function getAndRemoveAttr (line 6520) | function getAndRemoveAttr (
  function genComponentModel (line 6546) | function genComponentModel (
  function genAssignmentCode (line 6578) | function genAssignmentCode (
  function parseModel (line 6614) | function parseModel (val) {
  function next (line 6651) | function next () {
  function eof (line 6655) | function eof () {
  function isStringStart (line 6659) | function isStringStart (chr) {
  function parseBracket (line 6663) | function parseBracket (chr) {
  function parseString (line 6681) | function parseString (chr) {
  function model (line 6700) | function model (
  function genCheckboxModel (line 6751) | function genCheckboxModel (
  function genRadioModel (line 6782) | function genRadioModel (
  function genSelect (line 6794) | function genSelect (
  function genDefaultModel (line 6811) | function genDefaultModel (
  function normalizeEvents (line 6867) | function normalizeEvents (on) {
  function createOnceHandler (line 6886) | function createOnceHandler (handler, event, capture) {
  function add$1 (line 6896) | function add$1 (
  function remove$2 (line 6914) | function remove$2 (
  function updateDOMListeners (line 6927) | function updateDOMListeners (oldVnode, vnode) {
  function updateDOMProps (line 6946) | function updateDOMProps (oldVnode, vnode) {
  function shouldUpdateValue (line 6997) | function shouldUpdateValue (elm, checkVal) {
  function isNotInFocusAndDirty (line 7005) | function isNotInFocusAndDirty (elm, checkVal) {
  function isDirtyWithModifiers (line 7015) | function isDirtyWithModifiers (elm, newVal) {
  function normalizeStyleData (line 7054) | function normalizeStyleData (data) {
  function normalizeStyleBinding (line 7064) | function normalizeStyleBinding (bindingStyle) {
  function getStyle (line 7078) | function getStyle (vnode, checkChild) {
  function updateStyle (line 7148) | function updateStyle (oldVnode, vnode) {
  function addClass (line 7202) | function addClass (el, cls) {
  function removeClass (line 7227) | function removeClass (el, cls) {
  function resolveTransition (line 7260) | function resolveTransition (def) {
  function nextFrame (line 7320) | function nextFrame (fn) {
  function addTransitionClass (line 7326) | function addTransitionClass (el, cls) {
  function removeTransitionClass (line 7334) | function removeTransitionClass (el, cls) {
  function whenTransitionEnds (line 7341) | function whenTransitionEnds (
  function getTransitionInfo (line 7374) | function getTransitionInfo (el, expectedType) {
  function getTimeout (line 7423) | function getTimeout (delays, durations) {
  function toMs (line 7434) | function toMs (s) {
  function enter (line 7440) | function enter (vnode, toggleDisplay) {
  function leave (line 7589) | function leave (vnode, rm) {
  function checkDuration (line 7692) | function checkDuration (val, name, vnode) {
  function isValidDuration (line 7708) | function isValidDuration (val) {
  function getHookArgumentsLength (line 7718) | function getHookArgumentsLength (fn) {
  function _enter (line 7735) | function _enter (_, vnode) {
  function setSelected (line 7842) | function setSelected (el, binding, vm) {
  function actuallySetSelected (line 7852) | function actuallySetSelected (el, binding, vm) {
  function hasNoMatchingOption (line 7885) | function hasNoMatchingOption (value, options) {
  function getValue (line 7889) | function getValue (option) {
  function onCompositionStart (line 7895) | function onCompositionStart (e) {
  function onCompositionEnd (line 7899) | function onCompositionEnd (e) {
  function trigger (line 7906) | function trigger (el, type) {
  function locateNode (line 7915) | function locateNode (vnode) {
  function getRealChild (line 8006) | function getRealChild (vnode) {
  function extractTransitionData (line 8015) | function extractTransitionData (comp) {
  function placeholder (line 8031) | function placeholder (h, rawChild) {
  function hasParentTransition (line 8039) | function hasParentTransition (vnode) {
  function isSameChild (line 8047) | function isSameChild (child, oldChild) {
  function callPendingCbs (line 8311) | function callPendingCbs (c) {
  function recordPosition (line 8322) | function recordPosition (c) {
  function applyTranslation (line 8326) | function applyTranslation (c) {
  function parseText (line 8405) | function parseText (
  function transformNode (line 8435) | function transformNode (el, options) {
  function genData (line 8458) | function genData (el) {
  function transformNode$1 (line 8477) | function transformNode$1 (el, options) {
  function genData$1 (line 8502) | function genData$1 (el) {
  function decodeAttr (line 8602) | function decodeAttr (value, shouldDecodeNewlines) {
  function parseHTML (line 8607) | function parseHTML (html, options) {
  function createASTElement (line 8887) | function createASTElement (
  function parse (line 8905) | function parse (
  function processPre (line 9132) | function processPre (el) {
  function processRawAttrs (line 9138) | function processRawAttrs (el) {
  function processElement (line 9154) | function processElement (element, options) {
  function processKey (line 9170) | function processKey (el) {
  function processRef (line 9180) | function processRef (el) {
  function processFor (line 9188) | function processFor (el) {
  function processIf (line 9213) | function processIf (el) {
  function processIfConditions (line 9232) | function processIfConditions (el, parent) {
  function findPrevElement (line 9247) | function findPrevElement (children) {
  function addIfCondition (line 9264) | function addIfCondition (el, condition) {
  function processOnce (line 9271) | function processOnce (el) {
  function processSlot (line 9278) | function processSlot (el) {
  function processComponent (line 9327) | function processComponent (el) {
  function processAttrs (line 9337) | function processAttrs (el) {
  function checkInFor (line 9420) | function checkInFor (el) {
  function parseModifiers (line 9431) | function parseModifiers (name) {
  function makeAttrsMap (line 9440) | function makeAttrsMap (attrs) {
  function isTextTag (line 9455) | function isTextTag (el) {
  function isForbiddenTag (line 9459) | function isForbiddenTag (el) {
  function guardIESVGBug (line 9473) | function guardIESVGBug (attrs) {
  function checkForAliasModel (line 9485) | function checkForAliasModel (el, value) {
  function preTransformNode (line 9513) | function preTransformNode (el, options) {
  function cloneASTElement (line 9564) | function cloneASTElement (el) {
  function addRawAttr (line 9568) | function addRawAttr (el, name, value) {
  function text (line 9585) | function text (el, dir) {
  function html (line 9593) | function html (el, dir) {
  function optimize (line 9638) | function optimize (root, options) {
  function genStaticKeys$1 (line 9648) | function genStaticKeys$1 (keys) {
  function markStatic$1 (line 9655) | function markStatic$1 (node) {
  function markStaticRoots (line 9687) | function markStaticRoots (node, isInFor) {
  function isStatic (line 9717) | function isStatic (node) {
  function isDirectChildOfTemplateFor (line 9734) | function isDirectChildOfTemplateFor (node) {
  function genHandlers (line 9783) | function genHandlers (
  function genHandler (line 9795) | function genHandler (
  function genKeyFilter (line 9853) | function genKeyFilter (keys) {
  function genFilterCode (line 9857) | function genFilterCode (key) {
  function on (line 9873) | function on (el, dir) {
  function bind$1 (line 9882) | function bind$1 (el, dir) {
  function generate (line 9912) | function generate (
  function genElement (line 9924) | function genElement (el, state) {
  function genStatic (line 9957) | function genStatic (el, state) {
  function genOnce (line 9964) | function genOnce (el, state) {
  function genIf (line 9990) | function genIf (
  function genIfConditions (line 10000) | function genIfConditions (
  function genFor (line 10027) | function genFor (
  function genData$2 (line 10059) | function genData$2 (el, state) {
  function genDirectives (line 10137) | function genDirectives (el, state) {
  function genInlineTemplate (line 10162) | function genInlineTemplate (el, state) {
  function genScopedSlots (line 10175) | function genScopedSlots (
  function genScopedSlot (line 10184) | function genScopedSlot (
  function genForScopedSlot (line 10201) | function genForScopedSlot (
  function genChildren (line 10217) | function genChildren (
  function getNormalizationType (line 10247) | function getNormalizationType (
  function needsNormalization (line 10270) | function needsNormalization (el) {
  function genNode (line 10274) | function genNode (node, state) {
  function genText (line 10284) | function genText (text) {
  function genComment (line 10290) | function genComment (comment) {
  function genSlot (line 10294) | function genSlot (el, state) {
  function genComponent (line 10313) | function genComponent (
  function genProps (line 10322) | function genProps (props) {
  function transformSpecialNewlines (line 10332) | function transformSpecialNewlines (text) {
  function detectErrors (line 10357) | function detectErrors (ast) {
  function checkNode (line 10365) | function checkNode (node, errors) {
  function checkEvent (line 10391) | function checkEvent (exp, text, errors) {
  function checkFor (line 10403) | function checkFor (node, text, errors) {
  function checkIdentifier (line 10410) | function checkIdentifier (
  function checkExpression (line 10425) | function checkExpression (exp, text, errors) {
  function createFunction (line 10447) | function createFunction (code, errors) {
  function createCompileToFunctionFn (line 10456) | function createCompileToFunctionFn (compile) {
  function createCompilerCreator (line 10544) | function createCompilerCreator (baseCompile) {
  function getShouldDecode (line 10622) | function getShouldDecode (href) {
  function getOuterHTML (line 10713) | function getOuterHTML (el) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/Api2DocDemoApp.java
  class Api2DocDemoApp (line 13) | @EnableApi2Doc
    method main (line 18) | public static void main(String[] args) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/CodeGenerator.java
  class CodeGenerator (line 15) | public class CodeGenerator {
    method genAndroidCode (line 18) | public static void genAndroidCode(ApplicationContext context) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/FileInfo.java
  class FileInfo (line 8) | public class FileInfo {
    method FileInfo (line 16) | public FileInfo() {
    method parse (line 19) | public static FileInfo parse(MultipartFile file, String name) throws I...
    method FileInfo (line 26) | public FileInfo(String name, String content, String msg) {
    method getName (line 32) | public String getName() {
    method setName (line 36) | public void setName(String name) {
    method getContent (line 40) | public String getContent() {
    method setContent (line 44) | public void setContent(String content) {
    method getMsg (line 48) | public String getMsg() {
    method setMsg (line 52) | public void setMsg(String msg) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowMappingController.java
  class ShowMappingController (line 13) | @Api2Doc(value = "mapping", name = "演示各种Mapping生成文档", order = 100)
    method doRequest (line 20) | @ApiComment(value = "返回 doRequest 的消息文本", sample = "doRequest, id = 123")
    method doGet (line 30) | @GetMapping(value = "/doGet/{id}", name = "演示 @GetMapping 方法")
    method doPost (line 39) | @PostMapping(value = "/doPost/{id}", name = "演示 @PostMapping 方法")
    method doPut (line 49) | @PutMapping(value = "/doPut/{id}", name = "演示 @PutMapping 方法")
    method doDelete (line 59) | @DeleteMapping(value = "/doDelete/{id}", name = "演示 @DeleteMapping 方法")
    method doPatch (line 68) | @PatchMapping(value = "/doPatch/{id}", name = "演示 @PatchMapping 方法")

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowParamController.java
  class ShowParamController (line 14) | @Api2Doc(value = "params", name = "演示各种参数生成文档", order = 200)
    method requestParam (line 19) | @ApiComment(value = "返回消息文本", sample = "requestParam, key = 简单")
    method pathVariable (line 27) | @RequestMapping(value = "/path/{key}", name = "@PathVariable")
    method requestHeader (line 38) | @RequestMapping(value = "/header", name = "@RequestHeader")
    method cookieValue (line 55) | @RequestMapping(value = "/cookie", method = RequestMethod.GET,
    method requestPart (line 66) | @RequestMapping(value = "/part", method = RequestMethod.POST,

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowResultController.java
  class ShowResultController (line 16) | @Api2Doc(value = "results", name = "演示各种返回类型生成文档", order = 300)
    method getString (line 21) | @ApiComment(value = "返回简单的字符串", sample = "getString: abc")
    method getDate (line 28) | @ApiComment(value = "返回简单的Date类型", sample = "1522851993490")
    method getStrings (line 34) | @ApiComment(value = "返回数组类型,其元素为简单 String 类型", sample = "3")
    method getUser (line 43) | @ApiComment(value = "返回自定义JavaBean类型")
    method getUsers (line 49) | @ApiComment(value = "返回数组类型,其中的元素为自定义JavaBean类型")

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/User.java
  class User (line 8) | public class User {
    method getCreateTime (line 32) | public Date getCreateTime() {
    method setCreateTime (line 36) | public void setCreateTime(Date createTime) {
    method getId (line 40) | public Long getId() {
    method setId (line 44) | public void setId(Long id) {
    method getName (line 48) | public String getName() {
    method setName (line 52) | public void setName(String name) {
    method getPassword (line 56) | public String getPassword() {
    method setPassword (line 60) | public void setPassword(String password) {
    method getType (line 64) | public UserType getType() {
    method setType (line 68) | public void setType(UserType type) {
    method getDeleted (line 72) | public Boolean getDeleted() {
    method setDeleted (line 76) | public void setDeleted(Boolean deleted) {
    method getGroup (line 80) | public String getGroup() {
    method setGroup (line 84) | public void setGroup(String group) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController.java
  class UserController (line 11) | @Api2Doc(id = "demo", name = "演示Api2Doc基本用法", order = 0)
    method getUser (line 18) | @Api2Doc(order = 10)
    method getUsers (line 27) | @Api2Doc(order = 20)
    method getGroup (line 36) | @Api2Doc(order = 30)
    method addUser (line 45) | @Api2Doc(order = 40)
    method delete (line 56) | @Api2Doc(order = 50)

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController1.java
  class UserController1 (line 9) | @Api2Doc(id = "demo1", name = "演示 seeClass 的用法", order = 10)
    method addUser (line 15) | @ApiComment("添加一个新的用户。\n" +

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController2.java
  class UserController2 (line 12) | @Api2Doc(id = "demo2", name = "演示用 order 给文档排序的用法", order = 20)
    method addUser (line 18) | @Api2Doc(order = 10)
    method getUser (line 29) | @Api2Doc(order = 20)
    method getUsers (line 37) | @Api2Doc(order = 30)
    method getGroup (line 45) | @Api2Doc(order = 40)

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController3.java
  class UserController3 (line 9) | @Api2Doc(id = "demo3", name = "演示添加补充文档的用法", order = 30)
    method m1 (line 14) | @Api2Doc(order = 10)
    method m2 (line 19) | @Api2Doc(order = 20)
    method doSomethingRequiredLogon (line 24) | @RequestMapping(value = "/do_something")

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserGroup.java
  class UserGroup (line 8) | @ApiComment("一组用户的信息")
    method getUsers (line 17) | public List<User> getUsers() {
    method setUsers (line 21) | public void setUsers(List<User> users) {

FILE: commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserType.java
  type UserType (line 5) | public enum UserType {

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocCollectorTest.java
  class Api2DocCollectorTest (line 17) | @RunWith(SpringJUnit4ClassRunner.class)
    class User (line 22) | public static class User {
      method getId (line 27) | public Long getId() {
      method setId (line 31) | public void setId(Long id) {
    class UserController (line 36) | @Api2Doc(id = "user", name = "用户相关接口", order = 0)
      method getUser (line 41) | @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
      method getUsers (line 46) | @RequestMapping(value = "/users", method = RequestMethod.GET)
      method insert (line 51) | @RequestMapping(value = "/user/{id}", method = RequestMethod.POST)
      method delete (line 58) | @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    method testToApiFolder (line 64) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocObjectFactoryTest.java
  class Api2DocObjectFactoryTest (line 12) | public class Api2DocObjectFactoryTest {
    type UserType (line 16) | public enum UserType {
    class User (line 29) | public static class User {
      method getMate (line 52) | public User getMate() {
      method setMate (line 56) | public void setMate(User mate) {
      method getChildren (line 60) | public List<User> getChildren() {
      method setChildren (line 64) | public void setChildren(List<User> children) {
      method getId (line 68) | public Long getId() {
      method setId (line 72) | public void setId(Long id) {
      method getName (line 76) | public String getName() {
      method setName (line 80) | public void setName(String name) {
      method getType (line 84) | public UserType getType() {
      method setType (line 88) | public void setType(UserType type) {
      method getDeleted (line 92) | public Boolean getDeleted() {
      method setDeleted (line 96) | public void setDeleted(Boolean deleted) {
      method getTitles (line 100) | public String[] getTitles() {
      method setTitles (line 104) | public void setTitles(String[] titles) {
    method testCreateList (line 109) | @Test
    method testCreateArray (line 117) | @Test
    method testCreateObject (line 125) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocUtilsTest.java
  class Api2DocUtilsTest (line 19) | @RunWith(SpringJUnit4ClassRunner.class)
    class Api2DocUtilsTestController (line 24) | @Api2Doc(id = "user", name = "用户相关接口", order = 0)
      method getUser (line 29) | @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
      method getUser2 (line 36) | @RequestMapping(value = "/user2/{id}", method = RequestMethod.GET)
      method getUsers (line 45) | @RequestMapping(value = "/group/{groupId}/users", method = RequestMe...
    method testToURL (line 59) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ApiCommentUtilsTest.java
  class ApiCommentUtilsTest (line 21) | public class ApiCommentUtilsTest {
    class MyObject (line 23) | public class MyObject {
      method getId (line 31) | public Long getId() {
      method setId (line 35) | public void setId(Long id) {
      method getName (line 39) | public String getName() {
      method setName (line 43) | public void setName(String name) {
    class MyController (line 49) | @Api2Doc
      method updateUser (line 54) | @RequestMapping(value = "/user/{userId}")
    method testSee (line 63) | @Test
    class AnotherObject (line 75) | public class AnotherObject {
      method getName (line 80) | public String getName() {
      method setName (line 84) | public void setName(String name) {
    method testGetComment (line 89) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ApiResultObjectTest.java
  class ApiResultObjectTest (line 21) | @RunWith(SpringJUnit4ClassRunner.class)
    type UserType (line 26) | public enum UserType {
    class User (line 36) | public static class User {
      method getId (line 59) | public Long getId() {
      method setId (line 63) | public void setId(Long id) {
      method getUsername (line 67) | public String getUsername() {
      method setUsername (line 71) | public void setUsername(String username) {
      method getPassword (line 75) | public String getPassword() {
      method setPassword (line 79) | public void setPassword(String password) {
      method getState (line 83) | public UserType getState() {
      method setState (line 87) | public void setState(UserType state) {
      method getDeleted (line 91) | public Boolean getDeleted() {
      method setDeleted (line 95) | public void setDeleted(Boolean deleted) {
    method getUsers (line 101) | public final List<User> getUsers() {
    method testParseResultType (line 105) | @Test
    method getMessage (line 119) | @ApiComment("消息内容")
    method testParseResultTypeWithSimple (line 124) | @Test
    method testParseResultTypeWithIgnore (line 137) | @Test
    class DateBean (line 148) | public static class DateBean {
      method getCurrent (line 154) | public Date getCurrent() {
      method setCurrent (line 158) | public void setCurrent(Date current) {
    method getDateBean (line 163) | public DateBean getDateBean() {
    method testParseResultTypeWithDate (line 167) | @Test
    method getList (line 180) | public final List<String> getList() {
    method getSet (line 184) | public final Set<String> getSet() {
    method getArray (line 188) | public final String[] getArray() {
    method getMap (line 192) | public final Map<String, Object> getMap() {
    method testGetArrayElementClass (line 196) | @Test
    class NotOrderBean (line 215) | public static class NotOrderBean {
      method getAbc (line 225) | public String getAbc() {
      method setAbc (line 229) | public void setAbc(String abc) {
      method getAbd (line 233) | public String getAbd() {
      method setAbd (line 237) | public void setAbd(String abd) {
      method getB1 (line 241) | public String getB1() {
      method setB1 (line 245) | public void setB1(String b1) {
      method getB2 (line 249) | public String getB2() {
      method setB2 (line 253) | public void setB2(String b2) {
    method getNotOrderBean (line 258) | public NotOrderBean getNotOrderBean() {
    method testParseResultTypeWithNotOrder (line 262) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/Application.java
  class Application (line 7) | @EnableApi2Doc

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/BaseApi2DocTest.java
  class BaseApi2DocTest (line 12) | @RestController
    method loadDoc (line 20) | protected ApiDocObject loadDoc(String methodName) throws BusinessExcep...

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/CurlBuilderTest.java
  class CurlBuilderTest (line 16) | @Api2Doc(id = "curl")
    method withGet (line 20) | @RequestMapping(value = "/getting", method = RequestMethod.GET)
    method testToCurlWithGet (line 26) | @Test
    method simple (line 36) | @RequestMapping(value = "/normal/{p1}/abc/{p2}",
    method testToCurlSimple (line 46) | @Test
    method withComment (line 59) | @RequestMapping(value = "/comment/{p1}/{p2}",
    method testToCurlWithComment (line 78) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/JavaBeanCodeWriterTest.java
  class JavaBeanCodeWriterTest (line 24) | @SpringBootTest(classes = { Application.class }, webEnvironment = WebEnv...
    class User (line 30) | public class User {
      method getName (line 36) | public String getName() {
      method setName (line 40) | public void setName(String name) {
      method getRegistTime (line 44) | public Date getRegistTime() {
      method setRegistTime (line 48) | public void setRegistTime(Date registTime) {
    method getUser (line 54) | public final User getUser() {
    method testGetModel (line 61) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/MyBean.java
  class MyBean (line 12) | public class MyBean {
    method isOpen (line 30) | public boolean isOpen() {
    method setOpen (line 34) | public void setOpen(boolean open) {
    method getCounter (line 38) | public int getCounter() {
    method setCounter (line 42) | public void setCounter(int counter) {
    method getMessage (line 46) | public String getMessage() {
    method setMessage (line 50) | public void setMessage(String message) {
    method getCreateTime (line 54) | public Date getCreateTime() {
    method setCreateTime (line 58) | public void setCreateTime(Date createTime) {
    method getUsers (line 62) | public List<User> getUsers() {
    method setUsers (line 66) | public void setUsers(List<User> users) {
    method getChildren2 (line 70) | public MyBean[] getChildren2() {
    method setChildren2 (line 74) | public void setChildren2(MyBean[] children2) {
    method getChildren3 (line 78) | public Set<MyBean> getChildren3() {
    method setChildren3 (line 82) | public void setChildren3(Set<MyBean> children3) {

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnMethod.java
  class ParseApiCommentOnMethod (line 18) | @RunWith(SpringJUnit4ClassRunner.class)
    class User (line 23) | public class User {
      method getId (line 29) | public Long getId() {
      method setId (line 33) | public void setId(Long id) {
      method getUsername (line 37) | @Api2Doc(order = 20)
    method getUser (line 45) | public final User getUser() {
    method testParseApiCommentOnMethod (line 49) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnParam.java
  class ParseApiCommentOnParam (line 19) | @RunWith(SpringJUnit4ClassRunner.class)
    class User (line 24) | @ApiComment
      method getId (line 35) | public Long getId() {
      method setId (line 39) | public void setId(Long id) {
      method getName (line 43) | public String getName() {
      method setName (line 47) | public void setName(String name) {
    method setUser (line 52) | public final void setUser(
    method testParseApiCommentOnParam (line 58) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnSeeClass.java
  class ParseApiCommentOnSeeClass (line 23) | @RunWith(SpringJUnit4ClassRunner.class)
    class Comments (line 28) | public class Comments {
      method getId (line 36) | public Long getId() {
      method setId (line 40) | public void setId(Long id) {
      method getName (line 44) | public Long getName() {
      method setName (line 48) | public void setName(Long name) {
    class User (line 53) | @ApiComment(seeClass = Comments.class)
      method getId (line 60) | public Long getId() {
      method setId (line 64) | public void setId(Long id) {
      method getName (line 68) | public Long getName() {
      method setName (line 72) | public void setName(Long name) {
    class MyController (line 77) | @Api2Doc
      method updateUser (line 83) | @RequestMapping(value = "/user/{id}")
    method testParseApiCommentOnSeeClass (line 91) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnSeeClassLoop.java
  class ParseApiCommentOnSeeClassLoop (line 23) | @RunWith(SpringJUnit4ClassRunner.class)
    class Comments (line 29) | public class Comments {
      method getId (line 37) | public Long getId() {
      method setId (line 41) | public void setId(Long id) {
      method getName (line 45) | public Long getName() {
      method setName (line 49) | public void setName(Long name) {
    class User (line 54) | @ApiComment(seeClass = Comments.class)
      method getId (line 61) | public Long getId() {
      method setId (line 65) | public void setId(Long id) {
      method getName (line 69) | public Long getName() {
      method setName (line 73) | public void setName(Long name) {
    class MyController (line 78) | @Api2Doc
      method updateUser (line 84) | @RequestMapping(value = "/user/{id}")
    method testParseApiCommentOnSeeClassLoop (line 92) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseEnumTest.java
  class ParseEnumTest (line 15) | public class ParseEnumTest {
    type MyState (line 19) | public enum MyState {
    method getState (line 28) | public final MyState getState() {
    method testGetEnumComment (line 32) | @Test
    method testParseResultTypeWithEnum (line 38) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseListBeanTest.java
  class ParseListBeanTest (line 20) | @RunWith(SpringJUnit4ClassRunner.class)
    class User (line 25) | public class User {
      method getId (line 35) | public Long getId() {
      method setId (line 39) | public void setId(Long id) {
      method getUsername (line 43) | public String getUsername() {
      method setUsername (line 47) | public void setUsername(String username) {
    class ListBean (line 53) | public static class ListBean {
      method getUsers (line 58) | public List<User> getUsers() {
      method setUsers (line 62) | public void setUsers(List<User> users) {
    method getListBean (line 68) | public final ListBean getListBean() {
    method testGetSourceType (line 72) | @Test
    method testParseListBean (line 84) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ResultSourceTypeTest.java
  class ResultSourceTypeTest (line 17) | @RunWith(SpringJUnit4ClassRunner.class)
    class UserList (line 22) | public class UserList {
      method getUsers (line 26) | public List<User> getUsers() {
      method setUsers (line 30) | public void setUsers(List<User> users) {
    method getUsers (line 36) | public UserList getUsers() {
    method testGetResultSourceType (line 40) | @Test

FILE: commons-api2doc/src/test/java/com/terran4j/test/api2doc/ToMockResultTest.java
  class ToMockResultTest (line 14) | @Api2Doc(id = "toMockResult")
    class User (line 18) | public static class User {
      method getCreateTime (line 22) | public Date getCreateTime() {
      method setCreateTime (line 26) | public void setCreateTime(Date createTime) {
    method getDate (line 31) | @RequestMapping(value = "/getDate")
    method testDateResultType (line 36) | @Test
    method getUser (line 44) | @RequestMapping(value = "/getUser")
    method testDateInResultType (line 49) | @Test
    method getStrings (line 62) | @ApiComment(sample = "5")
    method testSimpleList (line 68) | @Test

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/ArmqConfig.java
  class ArmqConfig (line 10) | @Data
    method mqClient (line 26) | @Bean // destroyMethod = "close"
    method armqFactory (line 36) | @Bean

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/ConsumerConfig.java
  class ConsumerConfig (line 5) | @Data

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/MessageConsumer.java
  type MessageConsumer (line 5) | public interface MessageConsumer<T> {
    method onMessage (line 13) | void onMessage(String key, T content) throws BusinessException;

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/MessageService.java
  type MessageService (line 5) | public interface MessageService {
    method send (line 14) | void send(Object content, String key, String tag) throws BusinessExcep...
    method registConsumer (line 27) | <T> void registConsumer(MessageConsumer<T> consumer,
    method registConsumer (line 36) | <T> void registConsumer(MessageConsumer<T> consumer, Class<T> messageE...
    method unregistConsumer (line 39) | <T> void unregistConsumer(MessageConsumer<T> consumer);
    method unregistAllConsumers (line 41) | void unregistAllConsumers();

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageConsumerTask.java
  class MessageConsumerTask (line 16) | @Slf4j
    method MessageConsumerTask (line 21) | public MessageConsumerTask(MessageConsumerTransfer<T> transfer) {
    method execute (line 26) | @Override

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageConsumerTransfer.java
  class MessageConsumerTransfer (line 14) | @Slf4j
    method getConsumer (line 29) | public MessageConsumer<T> getConsumer() {
    method getMessageEntityClass (line 33) | public Class<T> getMessageEntityClass() {
    method getConfig (line 37) | public ConsumerConfig getConfig() {
    method getMqConsumer (line 41) | public MQConsumer getMqConsumer() {
    method MessageConsumerTransfer (line 45) | public MessageConsumerTransfer(MQConsumer mqConsumer,
    method stop (line 65) | public void stop() {
    method start (line 88) | public void start() throws BusinessException {

FILE: commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageServiceImpl.java
  class MessageServiceImpl (line 24) | @Slf4j
    method MessageServiceImpl (line 37) | public MessageServiceImpl(String instanceId, MQClient mqClient) {
    method getOrCreateProducer (line 42) | private MQProducer getOrCreateProducer(Class<?> messageEntityClass) th...
    method getMessageEntity (line 62) | private static MessageEntity getMessageEntity(Class<?> messageEntityCl...
    method getTopicName (line 78) | private static String getTopicName(MessageEntity messageEntity, Class<...
    method getGroupId (line 86) | private static String getGroupId(MessageEntity messageEntity, Class<?>...
    method getTopicName (line 97) | public static final <T> String getTopicName(Class<T> messageEntityClas...
    method send (line 103) | @Override
    method registConsumer (line 144) | @Override
    method registConsumer (line 150) | @Override
    method unregistConsumer (line 186) | @Override
    method unregistAllConsumers (line 193) | @Override

FILE: commons-armq/src/test/java/com/terran4j/commons/test/armq/ArmqTestApp.java
  class ArmqTestApp (line 7) | @Import(ArmqConfig.class)

FILE: commons-armq/src/test/java/com/terran4j/commons/test/armq/Normal.java
  class Normal (line 10) | @EqualsAndHashCode

FILE: commons-armq/src/test/java/com/terran4j/commons/test/armq/NormalTopicTest.java
  class NormalTopicTest (line 24) | @Slf4j
    method setUp (line 36) | @Before
    method tearDown (line 43) | @After
    method onMessage (line 48) | @Override
    method testNormalTopic (line 54) | @Test

FILE: commons-armq/src/test/java/com/terran4j/commons/test/armq/Producer.java
  class Producer (line 9) | public class Producer {
    method main (line 11) | public static void main(String[] args) {

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlExecutor.java
  type DsqlExecutor (line 13) | public interface DsqlExecutor {
    method query4List (line 23) | <T> List<T> query4List(SqlInfo sqlInfo, Class<T> elementType)
    method query4Count (line 31) | int query4Count(SqlInfo sqlInfo) throws BusinessException;
    method update (line 38) | int update(SqlInfo sqlInfo) throws BusinessException;

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlRepository.java
  type DsqlRepository (line 7) | public interface DsqlRepository<T> {

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/QueryBean.java
  class QueryBean (line 5) | public class QueryBean {
    method wrapWithLike (line 7) | public static final String wrapWithLike(String source) {
    method toString (line 27) | public String toString() {

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/config/DsqlConfiguration.java
  class DsqlConfiguration (line 7) | @ComponentScan(basePackageClasses = DsqlExecutorImpl.class)

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/CompositeBeanRowMapper.java
  class CompositeBeanRowMapper (line 19) | public class CompositeBeanRowMapper<T> implements RowMapper<T> {
    method newInstance (line 31) | public static <T> CompositeBeanRowMapper<T> newInstance(Class<T> mappe...
    method CompositeBeanRowMapper (line 35) | private CompositeBeanRowMapper(Class<T> mappedClass) {
    method initialize (line 39) | private void initialize(Class<T> mappedClass) {
    method mapRow (line 60) | @Override

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlBuilder.java
  class DsqlBuilder (line 21) | public class DsqlBuilder {
    method getInstance (line 27) | public static DsqlBuilder getInstance() {
    method DsqlBuilder (line 45) | private DsqlBuilder() {
    method getPath (line 58) | private String getPath(Class<?> clazz, String fileName) {
    method getTemplate (line 64) | private final Template getTemplate(Class<?> clazz, String fileName) {
    method build (line 98) | private final String build(Template template, Map<String, Object> mode...
    method buildSQL (line 110) | public final String buildSQL(Map<String, Object> model, Class<?> clazz...
    method buildPreparedArgs (line 140) | public final String buildPreparedArgs(String sql, List<String> keys) {

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlExecutorImpl.java
  class DsqlExecutorImpl (line 11) | public class DsqlExecutorImpl implements DsqlExecutor {
    method DsqlExecutorImpl (line 15) | public DsqlExecutorImpl() {
    method DsqlExecutorImpl (line 18) | public DsqlExecutorImpl(JdbcTemplate jdbcTemplate) {
    method getJdbcTemplate (line 22) | public JdbcTemplate getJdbcTemplate() {
    method setJdbcTemplate (line 26) | public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    method query4List (line 38) | @Override
    method query4Count (line 45) | @Override
    method update (line 58) | @Override

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryBeanFactory.java
  class DsqlRepositoryBeanFactory (line 9) | @Component
    method postProcessBeanDefinitionRegistry (line 12) | @Override
    method postProcessBeanFactory (line 18) | @Override

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryConfigRegistrar.java
  class DsqlRepositoryConfigRegistrar (line 25) | public class DsqlRepositoryConfigRegistrar implements ImportBeanDefiniti...
    method getApplicationContext (line 38) | public static final ApplicationContext getApplicationContext() {
    method getDsqlExecutor (line 42) | public static DsqlExecutor getDsqlExecutor() {
    method setApplicationContext (line 68) | @Override
    method registerBeanDefinitions (line 73) | @Override
    method registerBeanDefinitions (line 97) | void registerBeanDefinitions(DefaultListableBeanFactory registry, Clas...
    method registBean (line 124) | final void registBean(DefaultListableBeanFactory registry, Class<?> da...
    method registerBeanDefinitionIfNotExists (line 134) | boolean registerBeanDefinitionIfNotExists(
    method scanClasses (line 153) | final Set<Class<?>> scanClasses(Class<?> basePackageClass) {

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryProxy.java
  class DsqlRepositoryProxy (line 26) | public class DsqlRepositoryProxy implements MethodInterceptor {
    method createProxyObject (line 28) | public static final <T> T createProxyObject(Class<T> clazz) {
    method DsqlRepositoryProxy (line 49) | private DsqlRepositoryProxy(Class<?> proxyInterface) {
    method getElementType (line 54) | public Class<?> getElementType(Class<?> proxyInterface) {
    method intercept (line 71) | @Override
    method doModifying (line 125) | private Object doModifying(String sqlName, Map<String, Object> args,
    method doQuery (line 144) | private Object doQuery(String sqlName, Map<String, Object> args,
    method getContext (line 181) | private Map<String, Object> getContext(Method method, Object[] args) t...

FILE: commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/SqlInfo.java
  class SqlInfo (line 14) | public class SqlInfo {
    method getSql (line 22) | public String getSql() {
    method setSql (line 26) | public void setSql(String sql) {
    method getArgs (line 30) | public Object[] getArgs() {
    method setArgs (line 34) | public void setArgs(Object[] args) {
    method toString (line 38) | @Override
    method create (line 46) | public static SqlInfo create(Map<String, Object> context, Class<?> bas...

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/Address.java
  class Address (line 5) | @Entity(name = "demo_address")
    method Address (line 12) | public Address() {
    method Address (line 15) | public Address(String name, Double lon, Double lat) {
    method getId (line 38) | public Long getId() {
    method setId (line 42) | public void setId(Long id) {
    method getName (line 46) | public String getName() {
    method setName (line 50) | public void setName(String name) {
    method getLon (line 54) | public Double getLon() {
    method setLon (line 58) | public void setLon(Double lon) {
    method getLat (line 62) | public Double getLat() {
    method setLat (line 66) | public void setLat(Double lat) {

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDAO.java
  type AddressDAO (line 5) | public interface AddressDAO extends JpaRepository<Address, Long> {

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDistance.java
  class AddressDistance (line 5) | public class AddressDistance {
    method getAddress (line 13) | public Address getAddress() {
    method setAddress (line 17) | public void setAddress(Address address) {
    method getDistance (line 21) | public Long getDistance() {
    method setDistance (line 25) | public void setDistance(Long distance) {
    method toString (line 29) | public String toString() {

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDistanceDAO.java
  type AddressDistanceDAO (line 10) | public interface AddressDistanceDAO extends DsqlRepository<AddressDistan...
    method getNearest (line 12) | @DsqlQuery("address-nearest")
    method getNearest2 (line 15) | @DsqlQuery("address-nearest-2")
    method getAll (line 18) | @DsqlQuery("address-list")
    method count (line 21) | @DsqlQuery("address-count")
    method updateNearest (line 25) | @DsqlModifying("address-update-nearest")
    method deleteNearest (line 29) | @DsqlModifying("address-delete-nearest")

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressQuery.java
  class AddressQuery (line 5) | public class AddressQuery {
    method AddressQuery (line 15) | public AddressQuery(Double lat, Double lon) {
    method getName (line 20) | public String getName() {
    method setName (line 24) | public void setName(String name) {
    method isNearFirst (line 28) | public boolean isNearFirst() {
    method setNearFirst (line 32) | public void setNearFirst(boolean nearFirst) {
    method getLat (line 36) | public Double getLat() {
    method setLat (line 40) | public void setLat(Double lat) {
    method getLon (line 44) | public Double getLon() {
    method setLon (line 48) | public void setLon(Double lon) {
    method toString (line 52) | public final String toString() {

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/appdsql/DsqlDemoApplication.java
  class DsqlDemoApplication (line 20) | @EntityScan(basePackageClasses = Address.class)
    method run (line 35) | @Override
    method main (line 110) | public static void main(String[] args) {

FILE: commons-dsql/src/test/java/com/terran4j/demo/dsql/appjpa/JpaDemoApplication.java
  class JpaDemoApplication (line 21) | @EntityScan(basePackageClasses = Address.class)
    method run (line 32) | @Override
    method main (line 56) | public static void main(String[] args) {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/BaseDsqlTest.java
  class BaseDsqlTest (line 27) | @TruncateTable(basePackageClass = Location.class)
    class Application (line 35) | @EntityScan(basePackageClasses = Location.class)
    method setUp (line 68) | @Before

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlAutoTest.java
  class DsqlAutoTest (line 18) | public class DsqlAutoTest extends BaseDsqlTest {
    method testGetLocations (line 25) | @Test
    method testCountLocation (line 37) | @Test
    method testGetNearestLocation (line 46) | @Test

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlModifyingTest.java
  class DsqlModifyingTest (line 12) | public class DsqlModifyingTest extends BaseDsqlTest {
    method testUpdate (line 22) | @Test
    method testDelete (line 38) | @Test

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlQueryTest.java
  class DsqlQueryTest (line 16) | public class DsqlQueryTest extends BaseDsqlTest {
    method testQueryWithCompositeEntity (line 26) | @Test
    method testQueryWithExtendEntity (line 42) | @Test
    method testQueryWithParamAnno (line 58) | @Test
    method testCount (line 69) | @Test

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao/Location.java
  class Location (line 5) | @Entity(name = "test_location")
    method Location (line 11) | public Location() {
    method Location (line 14) | public Location(String name, Double lon, Double lat) {
    method getId (line 37) | public Long getId() {
    method setId (line 41) | public void setId(Long id) {
    method getName (line 45) | public String getName() {
    method setName (line 49) | public void setName(String name) {
    method getLon (line 53) | public Double getLon() {
    method setLon (line 57) | public void setLon(Double lon) {
    method getLat (line 61) | public Double getLat() {
    method setLat (line 65) | public void setLat(Double lat) {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao/LocationDAO.java
  type LocationDAO (line 5) | public interface LocationDAO extends JpaRepository<Location, Long> {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao/LocationQuery.java
  class LocationQuery (line 3) | public class LocationQuery {
    method isNearFirst (line 11) | public boolean isNearFirst() {
    method setNearFirst (line 15) | public void setNearFirst(boolean nearFirst) {
    method getLat (line 19) | public Double getLat() {
    method setLat (line 23) | public void setLat(Double lat) {
    method getLon (line 27) | public Double getLon() {
    method setLon (line 31) | public void setLon(Double lon) {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao1/LocationDsqlDAO.java
  type LocationDsqlDAO (line 8) | public interface LocationDsqlDAO extends DsqlRepository<Location> {
    method updateNearest (line 10) | @DsqlModifying("update-nearest")
    method deleteNearest (line 14) | @DsqlModifying("delete-nearest")

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/LocationDistance.java
  class LocationDistance (line 6) | public class LocationDistance  {
    method getLocation (line 12) | public Location getLocation() {
    method setLocation (line 16) | public void setLocation(Location location) {
    method getDistance (line 20) | public Long getDistance() {
    method setDistance (line 24) | public void setDistance(Long distance) {
    method toString (line 28) | public String toString() {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/LocationDistanceDAO.java
  type LocationDistanceDAO (line 10) | public interface LocationDistanceDAO extends DsqlRepository<LocationDist...
    method query (line 12) | @DsqlQuery("locations")
    method getNearest (line 15) | @DsqlQuery("location-nearest")

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/DistancedLocation.java
  class DistancedLocation (line 5) | public class DistancedLocation extends Location {
    method getDistance (line 9) | public Long getDistance() {
    method setDistance (line 13) | public void setDistance(Long distance) {

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/DistancedLocationDAO.java
  type DistancedLocationDAO (line 9) | public interface DistancedLocationDAO extends DsqlRepository<DistancedLo...
    method query (line 11) | @DsqlQuery("locations")
    method count (line 14) | @DsqlQuery("location-count")

FILE: commons-dsql/src/test/java/com/terran4j/test/dsql/dao4/LocationAutoDAO.java
  type LocationAutoDAO (line 10) | public interface LocationAutoDAO extends DsqlRepository<Location> {
    method getLocations (line 12) | List<Location> getLocations(LocationQuery query);
    method countLocation (line 14) | int countLocation(LocationQuery query);
    method getNearestLocation (line 16) | Location getNearestLocation(@Param("lat") Double lat, @Param("lon") Do...

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/CacheService.java
  type CacheService (line 12) | public interface CacheService {
    method existed (line 19) | boolean existed(String key);
    method remove (line 25) | void remove(String key);
    method setObject (line 33) | void setObject(String key, Object value, Long expiredMillisecond);
    method setObjectIfAbsent (line 42) | boolean setObjectIfAbsent(String key, Object value, Long expiredMillis...
    method getObject (line 50) | <T> T getObject(String key, Class<T> clazz) throws BusinessException;
    method setHashEntry (line 59) | void setHashEntry(String key, String entryKey, Object entryValue, Long...
    method getHashEntry (line 67) | <T> T getHashEntry(String key, String entryKey, Class<T> clazz) throws...
    method setHashMap (line 75) | <T> void setHashMap(String key, Map<String, T> map, Class<T> clazz);
    method getHashMap (line 83) | <T> Map<String, T> getHashMap(String key, Class<T> clazz) throws Busin...
    method sendMessage (line 93) | <T> boolean sendMessage(String channel, T message) throws BusinessExce...
    method deserialize (line 96) | <T> Object deserialize(byte[] bytes);

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/JedisCacheService.java
  class JedisCacheService (line 23) | @Deprecated
    method JedisCacheService (line 30) | public JedisCacheService(Jedis jedis) {
    method existed (line 35) | @Override
    method remove (line 45) | @Override
    method setObject (line 55) | @Override
    method getObject (line 85) | @Override
    method setHashEntry (line 109) | @Override
    method getHashEntry (line 130) | @Override
    method setHashMap (line 155) | @Override
    method getHashMap (line 171) | @Override
    method sendMessage (line 197) | @Override
    method deserialize (line 202) | @Override
    method setObjectIfAbsent (line 207) | @Override
    method setObjectNXXX (line 212) | private boolean setObjectNXXX(String key, Object value, Long expiredMi...

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/RedisTemplateCacheService.java
  class RedisTemplateCacheService (line 18) | public class RedisTemplateCacheService implements CacheService {
    method RedisTemplateCacheService (line 26) | public RedisTemplateCacheService(RedisTemplate<String, String> redisTe...
    method existed (line 34) | @Override
    method remove (line 42) | @Override
    method setObject (line 50) | @Override
    method getObject (line 68) | @Override
    method setHashEntry (line 92) | @Override
    method getHashEntry (line 113) | @Override
    method setHashMap (line 140) | @Override
    method getHashMap (line 159) | @Override
    method setObjectIfAbsent (line 187) | @Override
    method sendMessage (line 205) | @Override
    method deserialize (line 221) | @Override

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/config/HedisConfiguration.java
  class HedisConfiguration (line 41) | @Slf4j
    method cacheService (line 82) | @Bean
    method container (line 101) | @Bean
    method cacheManager (line 140) | @Bean
    method jedisConnectionFactory (line 146) | @Bean
    method jedis (line 185) | @Bean
    method redisson (line 192) | @Bean(destroyMethod = "shutdown")
    method redisTemplate (line 209) | @Bean
    method distributedSchedulingAspect (line 222) | @Bean
    method distributedSynchronizedAspect (line 228) | @Bean

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/DSchedulingAspect.java
  class DSchedulingAspect (line 35) | @Aspect
    method init (line 54) | @PostConstruct
    method distributedScheduling (line 60) | @Pointcut("@annotation(com.terran4j.commons.hedis.dschedule.DSchedulin...
    method doDistributedScheduling (line 64) | @Around("distributedScheduling()")
    method tolerableTimeDeviation (line 223) | long tolerableTimeDeviation() {
    method getMinPoint (line 228) | Long getMinPoint(Long a, long b) {
    method isValidTime (line 235) | boolean isValidTime(JobExeInfo lastInfo, Scheduled scheduled,
    method checkValue (line 305) | void checkValue(String value, Method method) throws BusinessException {
    method getResolver (line 339) | StringValueResolver getResolver() {

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/JobExeInfo.java
  class JobExeInfo (line 5) | public class JobExeInfo {
    method getBeginTime (line 26) | public final Long getBeginTime() {
    method setBeginTime (line 33) | public final void setBeginTime(Long beginTime) {
    method getEndTime (line 40) | public final Long getEndTime() {
    method setEndTime (line 47) | public final void setEndTime(Long endTime) {
    method getResultCode (line 54) | public final String getResultCode() {
    method setResultCode (line 61) | public final void setResultCode(String resultCode) {
    method getMessage (line 68) | public final String getMessage() {
    method setMessage (line 75) | public final void setMessage(String message) {
    method getInstanceId (line 82) | public final String getInstanceId() {
    method setInstanceId (line 89) | public final void setInstanceId(String instanceId) {
    method getClassName (line 96) | public final String getClassName() {
    method setClassName (line 103) | public final void setClassName(String className) {
    method getMethodName (line 110) | public final String getMethodName() {
    method setMethodName (line 117) | public final void setMethodName(String methodName) {
    method isRunning (line 124) | public final boolean isRunning() {
    method setRunning (line 131) | public final void setRunning(boolean running) {
    method toString (line 135) | public final String toString() {

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/DSynchArgs.java
  class DSynchArgs (line 6) | public class DSynchArgs {
    method set (line 10) | public static final void set(String key, Object value) {
    method get (line 19) | public static final Object get(String key) {
    method clear (line 27) | public static final void clear() {

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/DSynchronizedAspect.java
  class DSynchronizedAspect (line 33) | @Aspect
    method getExpression (line 43) | public static final Expression getExpression(String expEL) {
    method init (line 62) | @PostConstruct
    method distributedSynchronized (line 67) | @Pointcut("@annotation(com.terran4j.commons.hedis.dsyn.DSynchronized)")
    method doDistributedSynchronized (line 71) | @Around("distributedSynchronized()")
    method getLockKey (line 136) | public static String getLockKey(String keyEL, Object target, Method me...
    method doGetLockKey (line 146) | static String doGetLockKey(String keyEL, Object target, Method method,...
    method getNamesByAnno (line 178) | public static String[] getNamesByAnno(Method method) {

FILE: commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/Server.java
  class Server (line 5) | public class Server {
    method getInstanceId (line 9) | public static String getInstanceId() {

FILE: commons-hedis/src/main/java/com/terran4j/mock/hedis/MockCacheService.java
  class MockCacheService (line 10) | @Service
    method existed (line 15) | @Override
    method remove (line 20) | @Override
    method setObject (line 25) | @Override
    method setObjectIfAbsent (line 30) | @Override
    method getObject (line 39) | @SuppressWarnings("unchecked")
    method setHashEntry (line 45) | @Override
    method getHashEntry (line 59) | @SuppressWarnings({ "unchecked", "rawtypes" })
    method setHashMap (line 69) | @Override
    method getHashMap (line 74) | @SuppressWarnings("unchecked")
    method sendMessage (line 80) | @Override
    method deserialize (line 85) | @Override

FILE: commons-hedis/src/main/java/com/terran4j/mock/hedis/MockHedisConfig.java
  class MockHedisConfig (line 8) | @Configuration
    method cacheService (line 13) | @Bean

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/CountService.java
  class CountService (line 10) | @Service
    method doIncrementAndGet (line 19) | public int doIncrementAndGet(String key) {
    method incrementAndGet (line 49) | @DSynchronized("'incrementAndGet-' + #key")

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/DSynchronizedCountService.java
  class DSynchronizedCountService (line 12) | @Service
    method run (line 20) | @Override

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/DemoCacheService.java
  class DemoCacheService (line 13) | @Service
    method run (line 21) | @Override

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/HedisDemoApp.java
  class HedisDemoApp (line 8) | @EnableHedis
    method main (line 12) | public static void main(String[] args) {

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/LoopIncrementJob.java
  class LoopIncrementJob (line 10) | @Service
    method loopIncrement (line 20) | @DScheduling(lockExpiredSecond = 2)

FILE: commons-hedis/src/test/java/com/terran4j/demo/hedis/User.java
  class User (line 7) | public class User {
    method User (line 15) | public User() {
    method User (line 18) | public User(long id, String name, Date birthday) {
    method getId (line 24) | public long getId() {
    method setId (line 28) | public void setId(long id) {
    method getName (line 32) | public String getName() {
    method setName (line 36) | public void setName(String name) {
    method getBirthday (line 40) | public Date getBirthday() {
    method setBirthday (line 44) | public void setBirthday(Date birthday) {
    method toString (line 48) | @Override

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/BaseSpringBootTest.java
  class BaseSpringBootTest (line 8) | @RunWith(SpringJUnit4ClassRunner.class)

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/BaseTestExecutionListener.java
  class BaseTestExecutionListener (line 7) | public class BaseTestExecutionListener implements TestExecutionListener {
    method beforeTestClass (line 9) | @Override
    method prepareTestInstance (line 13) | @Override
    method beforeTestMethod (line 17) | @Override
    method afterTestMethod (line 21) | @Override
    method afterTestClass (line 25) | @Override
    method getSpringBootClasses (line 29) | protected final Class<?>[] getSpringBootClasses(TestContext testContex...

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/CacheAnnoTest.java
  class CacheAnnoTest (line 10) | public class CacheAnnoTest extends BaseCacheTest {
    method testCacheable (line 12) | @Test
    method testCachePut (line 29) | @Test
    method testCacheEvict (line 48) | @Test

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/JedisCacheServiceTest.java
  class JedisCacheServiceTest (line 16) | public class JedisCacheServiceTest extends BaseCacheTest {
    method createHome (line 20) | private Map<String, Home> createHome() {
    method testExistedAndRemove (line 34) | @Test
    method testSetAndGetObject (line 42) | @Test
    method testGetAndSetHashEntry (line 51) | @Test
    method testSetAndGetHashMap (line 60) | @Test
    method testConcurrent (line 69) | @Test

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/MockitoInitializer.java
  class MockitoInitializer (line 6) | public class MockitoInitializer extends BaseTestExecutionListener {
    method prepareTestInstance (line 8) | @Override

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/RedisTestConfig.java
  class RedisTestConfig (line 5) | @Configuration

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/RedissonClientTest.java
  class RedissonClientTest (line 14) | public class RedissonClientTest extends BaseCacheTest {
    method increment (line 23) | private int increment(int i) {
    method testLock (line 35) | @Test

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/SchedulingApplication.java
  class SchedulingApplication (line 15) | @EnableHedis // 一定要加这个,不然不会启动任务调度。
    method exe (line 24) | @DScheduling("SchedulingDemo")
    method main (line 34) | public static void main(String[] args) {

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/BaseCacheTest.java
  class BaseCacheTest (line 17) | @SpringBootTest(classes = { CacheTestApplication.class }, webEnvironment...
    method setUp (line 34) | @Before
    method tearDown (line 41) | @After

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/CacheTestApplication.java
  class CacheTestApplication (line 10) | @EnableHedis
    method homeService (line 15) | @Bean

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/CountService.java
  class CountService (line 9) | @Service
    method incrementAndGet (line 21) | public int incrementAndGet() throws BusinessException {

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/DSynchronizedService.java
  class DSynchronizedService (line 13) | @Service
    method incrementAndGet (line 30) | @DSynchronized(value = "'increment_' + #name")
    method getValue (line 48) | public int getValue(String name) throws BusinessException {
    method sleep (line 53) | private void sleep(long sleepTime) {

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/DSynchronizedTest.java
  class DSynchronizedTest (line 18) | public class DSynchronizedTest extends BaseCacheTest {
    method setUp (line 24) | @Before
    method toKey (line 31) | public String toKey() {
    method toKey (line 41) | public String toKey(int a, int b) {
    method doSomething (line 49) | public void doSomething(@Param("a") int a, @Param("b") int b) {
    method testGetLockKeyWithArgs (line 52) | @Test
    method testGetLockKey (line 70) | @Test
    method testDSynchronized (line 88) | @Test
    method testDSynchronizedMultiThread (line 97) | @Test

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/Home.java
  class Home (line 3) | public class Home {
    method Home (line 9) | public Home() {
    method Home (line 13) | public Home(String name) {
    method getName (line 18) | public String getName() {
    method setName (line 22) | public void setName(String name) {
    method getMemberCount (line 26) | public final int getMemberCount() {
    method setMemberCount (line 30) | public final void setMemberCount(int memberCount) {
    method toString (line 34) | @Override
    method hashCode (line 42) | @Override
    method equals (line 54) | @Override

FILE: commons-hedis/src/test/java/com/terran4j/test/hedis/dsyn/HomeService.java
  class HomeService (line 21) | @CacheConfig(cacheNames = "homes")
    method HomeService (line 37) | public HomeService() {
    method getActionTime (line 41) | public synchronized int getActionTime(String action) {
    method clear (line 45) | public void clear() {
    method create (line 54) | public Home create(String name) {
    method get (line 72) | @Cacheable(key = "'home-' + #name")
    method update (line 90) | @CachePut(key = "'home-' + #name")
    method delete (line 108) | @CacheEvict(key = "'home-' + #name")

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Action.java
  class Action (line 11) | public class Action {
    method getId (line 35) | public String getId() {
    method setId (line 39) | public void setId(String id) {
    method getName (line 43) | public String getName() {
    method setName (line 47) | public void setName(String name) {
    method getUrl (line 51) | public String getUrl() {
    method setUrl (line 55) | public void setUrl(String url) {
    method getMethod (line 59) | public String getMethod() {
    method setMethod (line 63) | public void setMethod(String method) {
    method getParams (line 67) | public Map<String, String> getParams() {
    method param (line 71) | public String param(String key) {
    method setParams (line 75) | public void setParams(Map<String, String> params) {
    method getHeaders (line 79) | public Map<String, String> getHeaders() {
    method setHeaders (line 83) | public void setHeaders(Map<String, String> headers) {
    method header (line 87) | public String header(String key) {
    method getHttpClient (line 91) | public HttpClient getHttpClient() {
    method setHttpClient (line 95) | public void setHttpClient(HttpClient httpClient) {
    method getWrites (line 99) | public List<Write> getWrites() {
    method setWrites (line 103) | public void setWrites(List<Write> writes) {
    method getPostBody (line 107) | public String getPostBody() {
    method setPostBody (line 111) | public void setPostBody(String postBody) {
    method getResponseBody (line 115) | public String getResponseBody() {
    method setResponseBody (line 119) | public void setResponseBody(String responseBody) {
    method getContent (line 123) | public JsonElement getContent() {
    method setContent (line 127) | public void setContent(JsonElement content) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/ApacheHttpClientBuilder.java
  class ApacheHttpClientBuilder (line 24) | public class ApacheHttpClientBuilder {
    method build (line 30) | public static final HttpClient build(int timeout, String charset) {
    class DefaultResponseHandler (line 46) | public static class DefaultResponseHandler implements ResponseHandler<...
      method handleResponse (line 48) | @Override

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Api2DocSupport.java
  class Api2DocSupport (line 23) | public class Api2DocSupport {
    method loadConfig (line 29) | public static final JsonObject loadConfig(String host, int port) throw...
    method toConfig (line 38) | static final JsonObject toConfig(JsonArray classMetas) {
    method toAction (line 59) | static final JsonObject toAction(MethodMeta method, String classId) {
    method loadClassMetas (line 100) | static final JsonArray loadClassMetas(String url) throws IOException {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/AssertResponseFailedException.java
  class AssertResponseFailedException (line 3) | public class AssertResponseFailedException extends RuntimeException {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/HttpClient.java
  class HttpClient (line 21) | public class HttpClient {
    method addListener (line 45) | public void addListener(HttpClientListener listener) {
    method getListeners (line 49) | public List<HttpClientListener> getListeners() {
    method createByApi2Doc (line 55) | public static final HttpClient createByApi2Doc(
    method create (line 62) | public static final HttpClient create(
    method create (line 80) | public static final HttpClient create(
    method create (line 86) | public static final HttpClient create(@NotNull File file,
    method create (line 116) | public static final HttpClient create(ApplicationContext context) {
    method HttpClient (line 120) | private HttpClient(JsonObject config, ApplicationContext context, Stri...
    method setApplicationContext (line 128) | public void setApplicationContext(ApplicationContext applicationContex...
    method init (line 135) | private void init(JsonObject config) {
    method getConfig (line 154) | public JsonObject getConfig() {
    method setConfig (line 158) | public void setConfig(JsonObject config) {
    method cloneLocals (line 162) | public Map<String, String> cloneLocals() {
    method getActions (line 168) | public Map<String, Action> getActions() {
    method createSession (line 172) | public Session createSession() {
    method getApplicationContext (line 176) | public ApplicationContext getApplicationContext() {
    method getHost (line 180) | public String getHost() {
    method setHost (line 184) | public HttpClient setHost(String host) {
    method getPort (line 189) | public int getPort() {
    method setPort (line 193) | public HttpClient setPort(int port) {
    method local (line 198) | public String local(String key) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/HttpClientListener.java
  type HttpClientListener (line 3) | public interface HttpClientListener {
    method beforeExecute (line 5) | void beforeExecute(HttpRequest request);
    method afterExecute (line 7) | String afterExecute(HttpRequest request, String response);

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/HttpErrorCode.java
  type HttpErrorCode (line 5) | public enum HttpErrorCode implements ErrorCode {
    method HttpErrorCode (line 23) | private HttpErrorCode(int value, String name) {
    method getValue (line 28) | public final int getValue() {
    method getName (line 32) | public final String getName() {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/HttpException.java
  class HttpException (line 5) | public class HttpException extends BusinessException {
    method HttpException (line 9) | public HttpException(HttpErrorCode code) {
    method HttpException (line 13) | public HttpException(HttpErrorCode code, Throwable cause) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/HttpRequest.java
  class HttpRequest (line 25) | public final class HttpRequest {
    method getMethod (line 43) | public RequestMethod getMethod() {
    method setMethod (line 47) | public HttpRequest setMethod(RequestMethod method) {
    method HttpRequest (line 56) | public HttpRequest(String url) {
    method getUrl (line 61) | public String getUrl() {
    method setParam (line 65) | public HttpRequest setParam(String key, String value) {
    method setParam (line 70) | public HttpRequest setParam(Map<String, String> params) {
    method setContent (line 75) | public HttpRequest setContent(String content) {
    method getParams (line 80) | public Map<String, String> getParams() {
    method setHeader (line 84) | public HttpRequest setHeader(String key, String value) {
    method setHeaders (line 89) | public HttpRequest setHeaders(Map<String, String> headers) {
    method toXml (line 94) | public static final String toXml(Map<String, String> params) {
    method addParams (line 109) | private static final void addParams(URIBuilder uriBuilder, Map<String,...
    method execute (line 120) | public String execute() throws HttpException {
    method toUrlQuery (line 222) | public static final String toUrlQuery(Map<String, String> params) {
    method encode (line 239) | private static String encode(String value) {
    method toCurl (line 247) | private String toCurl(HttpUriRequest request) {
    method getPostBody (line 274) | public String getPostBody() {
    method setPostBody (line 278) | public void setPostBody(String postBody) {
    method getResponseBody (line 282) | public String getResponseBody() {
    method setResponseBody (line 286) | public void setResponseBody(String responseBody) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Param.java
  class Param (line 3) | public class Param {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Request.java
  class Request (line 21) | public final class Request {
    method Request (line 46) | public Request(Action action, Session session, ApplicationContext appl...
    method buildContext (line 54) | private final ValueSources<String, String> buildContext() {
    method params (line 87) | public Request params(Properties props) {
    method param (line 101) | public Request param(String key, String value) {
    method sign (line 106) | public Request sign(String secretKey) {
    method sign (line 110) | public Request sign(String secretKey, String buildKey, String paramKey) {
    method content (line 126) | public Request content(String content) {
    method input (line 131) | public Request input(String key, String value) {
    method exe (line 136) | public void exe(final int threadCount, final int exeCountPerThread,
    method getContextValue (line 191) | public String getContextValue(String key) {
    method parseValue (line 195) | public String parseValue(String value) {
    method getActualURL (line 202) | public String getActualURL() {
    method getURLPrefix (line 211) | private String getURLPrefix() {
    method getActualParams (line 224) | public Map<String, String> getActualParams() throws BusinessException {
    method getActualContent (line 248) | public StringBuffer getActualContent() {
    method getActualHeaders (line 255) | public Map<String, String> getActualHeaders() {
    method parseValues (line 260) | private Map<String, String> parseValues(Map<String, String> map) {
    method buildSignParam (line 274) | private void buildSignParam(Map<String, String> params)
    method exe (line 296) | public Response exe() throws BusinessException {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Response.java
  class Response (line 12) | public final class Response {
    method Response (line 20) | public Response(ConfigElement result, Session session) {
    method getResult (line 26) | public ConfigElement getResult() {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Session.java
  class Session (line 8) | public final class Session {
    method Session (line 22) | Session(HttpClient service, ApplicationContext context) {
    method getHttpClient (line 35) | public HttpClient getHttpClient() {
    method getLocals (line 39) | public Map<String, String> getLocals() {
    method createRequest (line 47) | public Request createRequest(String action) throws HttpException {
    method getService (line 57) | public HttpClient getService() {
    method local (line 61) | public Session local(String key, String value) {
    method local (line 66) | public String local(String key) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/WrappedResponse.java
  class WrappedResponse (line 8) | @JsonInclude(JsonInclude.Include.NON_NULL)
    method success (line 31) | public static WrappedResponse success() {
    method success (line 38) | public static WrappedResponse success(Object data) {
    method fail (line 46) | public static WrappedResponse fail(BusinessException e) {
    method getRequestId (line 54) | public String getRequestId() {
    method setRequestId (line 58) | public void setRequestId(String requestId) {
    method getServerTime (line 62) | public long getServerTime() {
    method setServerTime (line 66) | public void setServerTime(long serverTime) {
    method getResultCode (line 70) | public int getResultCode() {
    method setResultCode (line 74) | public void setResultCode(int resultCode) {
    method getMessage (line 78) | public String getMessage() {
    method setMessage (line 82) | public void setMessage(String message) {
    method getData (line 86) | public Object getData() {
    method setData (line 90) | public void setData(Object data) {

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/Write.java
  class Write (line 9) | public class Write {
    method getKey (line 19) | public String getKey() {
    method setKey (line 23) | public void setKey(String key) {
    method getValue (line 27) | public String getValue() {
    method setValue (line 31) | public void setValue(String value) {
    method doWrite (line 43) | public void doWrite(Session session, final ValueSources<String, String...

FILE: commons-hi/src/main/java/com/terran4j/commons/hi/WriteTo.java
  type WriteTo (line 3) | public enum WriteTo {

FILE: commons-hi/src/test/java/com/terran4j/demo/hi/Calculator.java
  class Calculator (line 3) | public class Calculator {
    method Calculator (line 11) | public Calculator(long a, long b) {
    method getA (line 17) | public long getA() {
    method getB (line 21) | public long getB() {
    method getResult (line 25) | public long getResult() {
    method plus (line 29) | public Calculator plus() {

FILE: commons-hi/src/test/java/com/terran4j/demo/hi/CalculatorController.java
  class CalculatorController (line 5) | @RequestMapping("/calculator")
    method plus (line 9) | @RequestMapping("/plus")

FILE: commons-hi/src/test/java/com/terran4j/demo/hi/HttpClientApp.java
  class HttpClientApp (line 13) | @SpringBootApplication
    method main (line 16) | public static void main(String[] args) throws BusinessException {

FILE: commons-hi/src/test/java/com/terran4j/test/hi/BaseHiTest.java
  class BaseHiTest (line 10) | @RunWith(SpringJUnit4ClassRunner.class)
    method create (line 20) | protected final HttpClient create() {

FILE: commons-hi/src/test/java/com/terran4j/test/hi/HttpClientTest.java
  class HttpClientTest (line 10) | public class HttpClientTest extends BaseHiTest {
    method testLoadConfig (line 17) | @Test
    method testSessionLocal (line 40) | @Test
    method testGetContextValue (line 58) | @Test
    method testRequestInput (line 75) | @Test
    method testRequestContent (line 98) | @Test
    method testSign (line 119) | @Test

FILE: commons-hi/src/test/java/com/terran4j/test/hi/TestHiApp.java
  class TestHiApp (line 5) | @SpringBootApplication

FILE: commons-hi/src/test/java/com/terran4j/test/hi/api2doc/Api2DocApp.java
  class Api2DocApp (line 7) | @EnableRestPack

FILE: commons-hi/src/test/java/com/terran4j/test/hi/api2doc/Api2DocDemoController.java
  class Api2DocDemoController (line 9) | @Api2Doc("test")
    method multiply (line 14) | @RequestMapping(value = "/multiply", method = RequestMethod.POST)
    method echo (line 19) | @RequestMapping(value = "/echo", method = RequestMethod.GET)
    method put (line 24) | @RequestMapping(value = "/put/{id}", method = RequestMethod.PUT)
    method delete (line 30) | @RequestMapping(value = "/delete", method = RequestMethod.DELETE)

FILE: commons-hi/src/test/java/com/terran4j/test/hi/api2doc/Api2DocSupportTest.java
  class Api2DocSupportTest (line 17) | @RunWith(SpringJUnit4ClassRunner.class)
    method createClient (line 25) | private HttpClient createClient() {
    method testEcho (line 36) | @Test
    method testMultiply (line 45) | @Test
    method testPut (line 59) | @Test
    method testDelete (line 68) | @Test

FILE: commons-hi/src/test/java/com/terran4j/test/hi/api2doc/MultiplyObject.java
  class MultiplyObject (line 3) | public class MultiplyObject {
    method MultiplyObject (line 11) | public MultiplyObject(long a, long b) {
    method getA (line 17) | public long getA() {
    method setA (line 21) | public void setA(long a) {
    method getB (line 25) | public long getB() {
    method setB (line 29) | public void setB(long b) {
    method getResult (line 33) | public long getResult() {
    method setResult (line 37) | public void setResult(long result) {

FILE: commons-hi/src/test/java/com/terran4j/test/hi/exe/ExeController.java
  class ExeController (line 7) | @RequestMapping("/exe")
    method plus (line 11) | @RequestMapping(value = "/plus", method = RequestMethod.POST)
    method echo (line 17) | @RequestMapping(value = "/echo", method = RequestMethod.GET)

FILE: commons-hi/src/test/java/com/terran4j/test/hi/exe/ExeTest.java
  class ExeTest (line 11) | public class ExeTest extends BaseHiTest {
    method testEcho (line 13) | @Test
    method testPlus (line 23) | @Test

FILE: commons-hi/src/test/java/com/terran4j/test/hi/exe/PlusObject.java
  class PlusObject (line 3) | public class PlusObject {
    method PlusObject (line 11) | public PlusObject(long a, long b) {
    method getA (line 17) | public long getA() {
    method setA (line 21) | public void setA(long a) {
    method getB (line 25) | public long getB() {
    method setB (line 29) | public void setB(long b) {
    method getSum (line 33) | public long getSum() {
    method setSum (line 37) | public void setSum(long sum) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandDefine.java
  class CommandDefine (line 16) | public class CommandDefine {
    method CommandDefine (line 38) | public CommandDefine(CommandGroupDefine group, Object bean, Method met...
    method addOption (line 63) | public void addOption(CommandOptionDefine option) {
    method addOptions (line 67) | public void addOptions(CommandOptionDefine[] options) {
    method addOptions (line 71) | public void addOptions(List<CommandOptionDefine> options) {
    method getName (line 78) | public final String getName() {
    method setName (line 85) | public final void setName(String name) {
    method getExecutor (line 92) | public final CommandExecutor getExecutor() {
    method getOptions (line 99) | public final List<CommandOptionDefine> getOptions() {
    method getOption (line 103) | public final CommandOptionDefine getOption(String key) {
    method getGroup (line 115) | public final CommandGroupDefine getGroup() {
    method getHelp (line 119) | public String getHelp() {
    method getDesc (line 191) | public final String getDesc() {
    method setDesc (line 198) | public final void setDesc(String desc) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandErrorCode.java
  type CommandErrorCode (line 8) | public enum CommandErrorCode implements ErrorCode {
    method contains (line 40) | public static final boolean contains(ErrorCode code) {
    method CommandErrorCode (line 51) | private CommandErrorCode(int value, String name) {
    method getValue (line 59) | public final int getValue() {
    method getName (line 66) | public final String getName() {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandException.java
  class CommandException (line 5) | public class CommandException extends BusinessException {
    method CommandException (line 9) | public CommandException(String code) {
    method CommandException (line 13) | public CommandException(String code, Throwable cause) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandExecutor.java
  type CommandExecutor (line 7) | public interface CommandExecutor {
    method execute (line 9) | void execute(CommandInterpreter ci);

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandGroupDefine.java
  class CommandGroupDefine (line 12) | public class CommandGroupDefine {
    method CommandGroupDefine (line 22) | public CommandGroupDefine() {
    method CommandGroupDefine (line 26) | public CommandGroupDefine(CommandGroup anno) {
    method getCommands (line 32) | public List<CommandDefine> getCommands() {
    method size (line 36) | public int size() {
    method addCommand (line 40) | public void addCommand(CommandDefine commandDefine) {
    method getCommand (line 46) | public CommandDefine getCommand(String name) {
    method getName (line 50) | public String getName() {
    method setName (line 54) | public void setName(String name) {
    method getDesc (line 58) | public String getDesc() {
    method setDesc (line 62) | public void setDesc(String desc) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandGroups.java
  class CommandGroups (line 10) | public class CommandGroups {
    method addCommandGroup (line 16) | public void addCommandGroup(CommandGroupDefine group) {
    method containsKey (line 33) | public boolean containsKey(Object key) {
    method get (line 37) | public CommandGroupDefine get(Object key) {
    method put (line 41) | public CommandGroupDefine put(String key, CommandGroupDefine value) {
    method keySet (line 45) | public Set<String> keySet() {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandInterpreter.java
  type CommandInterpreter (line 7) | public interface CommandInterpreter {
    method hasOption (line 9) | boolean hasOption(String key);
    method getOption (line 11) | int getOption(String key, int defaultValue) throws BusinessException;
    method getOption (line 13) | String getOption(String key);
    method getOption (line 15) | String getOption(String key, String defaultValue);
    method getOption (line 17) | Properties getOption(String key, Properties defaultValue);
    method print (line 19) | void print(String msg);
    method println (line 21) | void println(String msg);
    method println (line 23) | void println(String msg, Object... args);
    method println (line 25) | void println();

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandOptionDefine.java
  class CommandOptionDefine (line 3) | public class CommandOptionDefine {
    method CommandOptionDefine (line 15) | public CommandOptionDefine(CommandOption option) {
    method getType (line 27) | public final OptionType getType() {
    method getKey (line 34) | public final String getKey() {
    method isRequired (line 41) | public final boolean isRequired() {
    method getName (line 48) | public final String getName() {
    method getDesc (line 55) | public final String getDesc() {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/CommandOptionType.java
  type CommandOptionType (line 7) | public enum CommandOptionType {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/Encoding.java
  type Encoding (line 3) | public enum Encoding {
    method Encoding (line 9) | private Encoding(String name){
    method getName (line 13) | public final String getName() {
    method getDefaultEncoding (line 17) | public static Encoding getDefaultEncoding(){

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/JFingerConfiguration.java
  class JFingerConfiguration (line 14) | @ComponentScan(basePackageClasses = { //

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/OptionType.java
  type OptionType (line 6) | public enum OptionType {
    method toValue (line 19) | public static final OptionType toValue(String name) {
    method OptionType (line 28) | private OptionType(String name) {
    method getName (line 35) | public final String getName() {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/builtin/LogCommand.java
  class LogCommand (line 11) | @CommandGroup(options = {}, desc = "Logback 日志相关命令,可以用于调整日志级别等操作。")
    method setLevel (line 14) | @Command(desc = "设置日志级别,如: log setLevel -n \"com.terran4j\" -l warn ",...

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/builtin/SpringCommand.java
  class SpringCommand (line 14) | @CommandGroup(options = {}, desc = "Spring 相关命令,如查看 Spring 中的配置属性等。")
    method setApplicationContext (line 19) | @Override
    method prop (line 24) | @Command( //
    method profile (line 36) | @Command( //
    method showBean (line 62) | @Command( //

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/builtin/SystemCommand.java
  class SystemCommand (line 16) | @CommandGroup(options = {}, desc = "系统命令,读取或写入本程序中的系统变量或环境变量等。")
    method setProps (line 21) | @Command(desc = "改写系统变量值,如: system setProps -Dk1=123 -Dk2=456", option...
    method prop (line 31) | @Command(desc = "显示或改写系统系统变量的值,如:\n" //
    method env (line 82) | @Command(desc = "读取或写入环境变量的值", options = { //

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/BackCommandException.java
  class BackCommandException (line 20) | public class BackCommandException extends RuntimeException {
    class ErrorInfo (line 42) | private static final class ErrorInfo {
      method ErrorInfo (line 48) | public ErrorInfo(String message) {
      method getMessage (line 56) | public final String getMessage() {
      method put (line 60) | public void put(String key, Object value) {
      method get (line 67) | public Object get(String key) {
    method getBundle (line 80) | private static final ResourceBundle getBundle() {
    method BackCommandException (line 93) | public BackCommandException(ErrorCode code) {
    method BackCommandException (line 98) | public BackCommandException(ErrorCode code, String message) {
    method BackCommandException (line 103) | public BackCommandException(ErrorCode code, Throwable cause) {
    method BackCommandException (line 108) | public BackCommandException(ErrorCode code, String message, Throwable ...
    method push (line 113) | public final BackCommandException push(String msg) {
    method setInfo (line 118) | public final BackCommandException setInfo(String key, Object value) {
    method getInfo (line 127) | public final Object getInfo(String key) {
    method wrap (line 134) | public static final BackCommandException wrap(ErrorCode code) {
    method wrap (line 138) | public static final BackCommandException wrap(ErrorCode code, String m...
    method wrap (line 142) | public static final BackCommandException wrap(ErrorCode code, Throwabl...
    method wrap (line 152) | public static final BackCommandException wrap(ErrorCode code, Throwabl...
    method getErrorCode (line 162) | public ErrorCode getErrorCode() {
    method getResource (line 166) | private String getResource(String key) {
    method toString (line 189) | private String toString(StackTraceElement element) {
    method getMessage (line 198) | @Override
    method getReport (line 207) | public String getReport() {
    method getDescription (line 233) | public String getDescription() {
    method putDetails (line 241) | private void putDetails(StringBuilder sb) {
    method getString (line 270) | private String getString(Object value) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/CommandInterpreterImpl.java
  class CommandInterpreterImpl (line 11) | public class CommandInterpreterImpl implements CommandInterpreter {
    method CommandInterpreterImpl (line 19) | public CommandInterpreterImpl(PrintStream out, CommandLine commandLine...
    method print (line 26) | public void print(String msg) {
    method println (line 30) | public void println(String msg) {
    method println (line 34) | public void println(String msg, Object... args) {
    method println (line 40) | public void println() {
    method hasOption (line 44) | public boolean hasOption(String key) {
    method getOption (line 48) | public int getOption(String key, int defaultValue) throws BusinessExce...
    method getOption (line 69) | public String getOption(String key) {
    method getOption (line 73) | public String getOption(String key, String defaultValue) {
    method getOption (line 81) | public Properties getOption(String key, Properties defaultValue) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/CommandLineApplicationListener.java
  class CommandLineApplicationListener (line 25) | @Service
    method getPrompt (line 38) | public static final String getPrompt() {
    method CommandLineApplicationListener (line 46) | public CommandLineApplicationListener() {
    method onApplicationEvent (line 50) | @Override
    method getCommandMethod (line 141) | private List<Method> getCommandMethod(Class<?> beanClass) {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/CommandLineService.java
  class CommandLineService (line 33) | @Service
    method CommandLineService (line 46) | public CommandLineService() {
    method getCommands (line 50) | public CommandGroups getCommands() {
    method setCommands (line 54) | public void setCommands(CommandGroups commands) {
    method getPrompt (line 58) | public String getPrompt() {
    method setPrompt (line 62) | public void setPrompt(String prompt) {
    method execute (line 66) | public final boolean execute(String command, PrintStream out) {
    method execute (line 136) | private void execute(String groupName, String commandName, CommandDefi...
    method printHelpPrompt (line 206) | private void printHelpPrompt(Throwable e, PrintStream out) {
    method getHelpPrompt (line 215) | public String getHelpPrompt() {
    method getHelp (line 235) | public String getHelp() {
    method getHelp (line 272) | public String getHelp(String groupName) {
    method getHelp (line 306) | public String getHelp(String groupName, String name) {
    method printPrompt (line 329) | public void printPrompt(PrintStream out) {
    method nextIndex (line 333) | public static final int[] nextIndex(String command, int fromIndex) thr...
    method parseCommand (line 383) | public static final String[] parseCommand(String command) throws Busin...

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/CommandLineTask.java
  class CommandLineTask (line 11) | public class CommandLineTask extends Thread {
    method CommandLineTask (line 17) | public CommandLineTask(CommandLineService service) {
    method run (line 22) | public void run() {

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/DynMethodCommandExecutor.java
  class DynMethodCommandExecutor (line 10) | public class DynMethodCommandExecutor implements CommandExecutor {
    method DynMethodCommandExecutor (line 18) | public DynMethodCommandExecutor(Object bean, Method method, String bea...
    method execute (line 25) | @Override

FILE: commons-jfinger/src/main/java/com/terran4j/commons/jfinger/impl/Util.java
  class Util (line 19) | public class Util {
    method getString (line 25) | public String getString(InputStream in) {
    method getString (line 29) | public String getString(Throwable t) {
    method getString (line 53) | public String getString(Class<?> clazz, String fileName) {
    method toInputStream (line 85) | public InputStream toInputStream(String s) {
    method getString (line 99) | public String getString(InputStream in, Encoding encoding) {
    method copy (line 128) | public long copy(InputStream input, OutputStream output) throws IOExce...
    method split (line 156) | public String[] split(String str) {
    method split (line 160) | public String[] split(String str, String split) {
    method split (line 164) | public String[] split(String str, String split, int limit) {
    method split (line 200) | public String[] split(String str, String begin, String end) {
    method getClassPath (line 232) | public String getClassPath(final Class<?> clazz, String fileName) {
    method encode (line 245) | public String encode(String str) {
    method decode (line 254) | public String decode(String str) {

FILE: commons-jfinger/src/test/java/com/terran4j/test/commons/jfinger/JFingerTestApplication.java
  class JFingerTestApplication (line 14) | @EnableJFinger
    method main (line 18) | public static void main(String[] args) throws Exception {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/Message.java
  class Message (line 11) | public class Message {
    method generateId (line 17) | public static final String generateId() {
    method getId (line 44) | public final String getId() {
    method setId (line 51) | public final void setId(String id) {
    method getType (line 58) | public final String getType() {
    method setType (line 65) | public final void setType(String type) {
    method getContent (line 72) | public final Object getContent() {
    method setContent (line 79) | public final void setContent(Object content) {
    method getStatus (line 86) | public final int getStatus() {
    method setStatus (line 93) | public final void setStatus(int status) {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/RefluxClient.java
  type RefluxClient (line 5) | public interface RefluxClient {
    method connect (line 7) | boolean connect(String serverURL, String clientId) throws BusinessExce...

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/RefluxErrorCode.java
  type RefluxErrorCode (line 5) | public enum RefluxErrorCode implements ErrorCode {
    method RefluxErrorCode (line 24) | private RefluxErrorCode(int value, String name) {
    method getValue (line 29) | public final int getValue() {
    method getName (line 33) | public final String getName() {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/RefluxServer.java
  type RefluxServer (line 11) | public interface RefluxServer {
    method isConnected (line 18) | boolean isConnected(String clientId);
    method sendAll (line 31) | <T> int sendAll(T content);
    method send (line 40) | <T> boolean send(T content, String clientId);

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/Reply.java
  class Reply (line 8) | public class Reply<T> {
    method getData (line 29) | public final T getData() {
    method setData (line 36) | public final void setData(T data) {
    method getClientHost (line 43) | public final String getClientHost() {
    method setClientHost (line 50) | public final void setClientHost(String clientHost) {
    method getClientIP (line 57) | public final String getClientIP() {
    method setClientIP (line 64) | public final void setClientIP(String clientIP) {
    method getRequestTime (line 71) | public final long getRequestTime() {
    method setRequestTime (line 78) | public final void setRequestTime(long requestTime) {
    method getResponseTime (line 85) | public final long getResponseTime() {
    method setResponseTime (line 92) | public final void setResponseTime(long responseTime) {
    method getResultCode (line 99) | public final long getResultCode() {
    method setResultCode (line 106) | public final void setResultCode(long resultCode) {
    method getResultName (line 113) | public final String getResultName() {
    method setResultName (line 120) | public final void setResultName(String resultName) {
    method getMessage (line 127) | public final String getMessage() {
    method setMessage (line 134) | public final void setMessage(String message) {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/client/ClientConnection.java
  class ClientConnection (line 22) | @ClientEndpoint
    method ClientConnection (line 35) | public ClientConnection(String serverURL, String clientId, MessageHand...
    method isOpen (line 42) | public boolean isOpen() {
    method onOpen (line 46) | @OnOpen
    method onClose (line 54) | @OnClose
    method onMessage (line 66) | @OnMessage
    method sendMessage (line 93) | public void sendMessage(String message) throws IOException {
    method close (line 104) | public void close() throws IOException {
    method getMessageHandler (line 110) | public final MessageHandler getMessageHandler() {
    method getServerURL (line 114) | public final String getServerURL() {
    method getClientId (line 118) | public final String getClientId() {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/client/MessageHandler.java
  class MessageHandler (line 24) | @Service
    class OnMessageInvoker (line 33) | private static class OnMessageInvoker {
    method postProcessBeforeInitialization (line 42) | @Override
    method postProcessAfterInitialization (line 47) | @Override
    method onMessage (line 83) | public String onMessage(String message) throws BusinessException {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/client/RefluxClientConfiguration.java
  class RefluxClientConfiguration (line 6) | @ComponentScan(basePackageClasses = { RefluxClientImpl.class })

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/client/RefluxClientImpl.java
  class RefluxClientImpl (line 38) | @Service
    method getConnections (line 47) | static final Map<String, ClientConnection> getConnections() {
    method init (line 64) | @PostConstruct
    method execute (line 99) | @Override
    method reconnectAll (line 105) | boolean reconnectAll() {
    method connect (line 152) | @Override
    method getConnectInterval (line 201) | public long getConnectInterval() {
    method getContext (line 205) | ApplicationContext getContext() {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/server/ClientAppInfo.java
  class ClientAppInfo (line 3) | public class ClientAppInfo {
    method getMaxConnectionCount (line 9) | public int getMaxConnectionCount() {
    method setMaxConnectionCount (line 13) | public void setMaxConnectionCount(int maxConnectionCount) {
    method getAppKey (line 17) | public final String getAppKey() {
    method setAppKey (line 21) | public final void setAppKey(String appKey) {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/server/ClientConnectionInfo.java
  class ClientConnectionInfo (line 3) | public final class ClientConnectionInfo {
    method getEnvName (line 16) | public final String getEnvName() {
    method setEnvName (line 24) | public final void setEnvName(String envName) {
    method getClientId (line 31) | public final String getClientId() {
    method setClientId (line 39) | public final void setClientId(String clientId) {
    method getConnectedTime (line 46) | public final long getConnectedTime() {
    method setConnectedTime (line 54) | public final void setConnectedTime(long connectedTime) {
    method getConnection (line 61) | public final RefluxServerEndpoint getConnection() {
    method setConnection (line 69) | public final void setConnection(RefluxServerEndpoint connection) {
    method toString (line 73) | @Override

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/server/RefluxServerConfiguration.java
  class RefluxServerConfiguration (line 8) | @ComponentScan(basePackageClasses = { RefluxServerImpl.class })
    method serverEndpointExporter (line 12) | @Bean

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/server/RefluxServerEndpoint.java
  class RefluxServerEndpoint (line 25) | public abstract class RefluxServerEndpoint implements ApplicationContext...
    method setConnectionManager (line 31) | public static final void setConnectionManager(RefluxServerImpl connect...
    method getApplicationContext (line 43) | public final ApplicationContext getApplicationContext() {
    method setApplicationContext (line 47) | @Override
    method setSendable (line 52) | public final void setSendable(boolean sendable) {
    method close (line 56) | private void close(Session session) {
    method authenticate (line 82) | protected abstract boolean authenticate(String clientId);
    method getClientId (line 84) | protected String getClientId(Session session) {
    method onOpen (line 101) | @OnOpen
    method onClose (line 123) | @OnClose
    method onMessage (line 131) | @OnMessage
    method onError (line 138) | @OnError
    method isSendable (line 147) | public final boolean isSendable() {
    method sendMessage (line 151) | public final void sendMessage(String message) throws IOException {
    method getClientId (line 170) | String getClientId() {

FILE: commons-reflux/src/main/java/com/terran4j/commons/reflux/server/RefluxServerImpl.java
  class RefluxServerImpl (line 33) | @Service
    method saveMe (line 45) | @PostConstruct
    method onClose (line 50) | public void onClose(String clientId) {
    method onOpen (line 66) | public ClientConnectionInfo onOpen(String clientId, RefluxServerEndpoi...
    method getConnections (line 95) | public List<RefluxServerEndpoint> getConnections() {
    method getConnection (line 116) | public RefluxServerEndpoint getConnection(String clientId) {
    method getConnectionCount (line 124) | public int getConnectionCount() {
    type ConnectionHandler (line 128) | public static interface ConnectionHandler {
      method exe (line 129) | void exe(RefluxServerEndpoint conn);
    method dispatch (line 132) | public void dispatch(ConnectionHandler handler) {
    method isConnected (line 145) | @Override
    method send (line 150) | @Override
    method sendAll (line 175) | @Override
    method sendContent (line 205) | final <T> boolean sendContent(T content, ClientConnectionInfo info) {

FILE: commons-reflux/src/test/java/com/terran4j/test/commons/reflux/Hello.java
  class Hello (line 3) | public class Hello {
    method Hello (line 11) | public Hello() {
    method Hello (line 15) | public Hello(String name) {
    method Hello (line 19) | public Hello(String name, String greeting) {
    method getName (line 29) | public final String getName() {
    method setName (line 36) | public final void setName(String name) {
    method getGreeting (line 43) | public final String getGreeting() {
    method setGreeting (line 50) | public final void setGreeting(String greeting) {
    method getCurrentTime (line 57) | public final long getCurrentTime() {
    method setCurrentTime (line 64) | public final void setCurrentTime(long currentTime) {

FILE: commons-reflux/src/test/java/com/terran4j/test/commons/reflux/RefluxApplication.java
  class RefluxApplication (line 8) | @EnableReflux
    method main (line 12) | public static void main(String[] args) {

FILE: commons-reflux/src/test/java/com/terran4j/test/commons/reflux/SendAndReceiveTest.java
  class SendAndReceiveTest (line 26) | @SpringBootTest(classes = { RefluxApplication.class }, webEnvironment = ...
    method setUp (line 46) | @Before
    method onHello (line 53) | @OnMessage
    method testSendAndReceive (line 61) | @Test

FILE: commons-reflux/src/test/java/com/terran4j/test/commons/reflux/TestServerEndpoint.java
  class TestServerEndpoint (line 13) | @ServerEndpoint("/websocket/connect")
    method generateClientId (line 19) | public static final String generateClientId() {
    method authenticate (line 25) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/HttpResult.java
  class HttpResult (line 14) | @JsonInclude(JsonInclude.Include.NON_NULL)
    method success (line 38) | public static HttpResult success() {
    method success (line 44) | public static HttpResult success(Object data) {
    method successFully (line 55) | public static HttpResult successFully(Object data) {
    method fail (line 65) | public static HttpResult fail(ErrorCode errorCode, String msg) {
    method fail (line 78) | public static HttpResult fail(BusinessException e) {
    method clearPropsIfEmpty (line 94) | public void clearPropsIfEmpty() {
    method getRequestId (line 100) | public String getRequestId() {
    method setRequestId (line 104) | public void setRequestId(String requestId) {
    method getServerTime (line 108) | public long getServerTime() {
    method setServerTime (line 112) | public void setServerTime(long serverTime) {
    method getResultCode (line 116) | public String getResultCode() {
    method setResultCode (line 120) | public void setResultCode(String resultCode) {
    method getMessage (line 124) | public String getMessage() {
    method setMessage (line 128) | public void setMessage(String message) {
    method getData (line 132) | public Object getData() {
    method setData (line 136) | public void setData(Object data) {
    method getSpendTime (line 140) | public long getSpendTime() {
    method setSpendTime (line 144) | public void setSpendTime(long spendTime) {
    method getProps (line 148) | public Map<String, Object> getProps() {
    method setProps (line 152) | public void setProps(Map<String, Object> props) {
    method toString (line 156) | public final String toString() {
    method getLogs (line 160) | public List<String> getLogs() {
    method setLogs (line 164) | public void setLogs(List<String> logs) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/HttpResultConverter.java
  type HttpResultConverter (line 3) | public interface HttpResultConverter {
    method convert (line 5) | Object convert(HttpResult httpResult);

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/LogItem.java
  class LogItem (line 13) | public class LogItem {
    method toJson (line 17) | public static final String toJson(LogItem obj) {
    method fromJson (line 21) | public static final LogItem fromJson(String json) {
    method fromEvent (line 25) | public static final LogItem fromEvent(ILoggingEvent event) {
    method getLoggerName (line 106) | public String getLoggerName() {
    method setLoggerName (line 110) | public void setLoggerName(String loggerName) {
    method getMessage (line 114) | public String getMessage() {
    method setMessage (line 118) | public void setMessage(String message) {
    method getArgs (line 122) | public String[] getArgs() {
    method setArgs (line 126) | public void setArgs(String[] args) {
    method getLevelInt (line 130) | public int getLevelInt() {
    method setLevelInt (line 134) | public void setLevelInt(int levelInt) {
    method getThreadName (line 138) | public String getThreadName() {
    method setThreadName (line 142) | public void setThreadName(String threadName) {
    method getTimeStamp (line 146) | public long getTimeStamp() {
    method setTimeStamp (line 150) | public void setTimeStamp(long timeStamp) {
    method getServerName (line 154) | public String getServerName() {
    method setServerName (line 158) | public void setServerName(String serverName) {
    method getServerIP (line 162) | public String getServerIP() {
    method setServerIP (line 166) | public void setServerIP(String serverIP) {
    method getServerPort (line 170) | public int getServerPort() {
    method setServerPort (line 174) | public void setServerPort(int serverPort) {
    method getServiceName (line 178) | public String getServiceName() {
    method setServiceName (line 182) | public void setServiceName(String serviceName) {
    method getDeclaringClass (line 186) | public String getDeclaringClass() {
    method setDeclaringClass (line 190) | public void setDeclaringClass(String declaringClass) {
    method getMethodName (line 194) | public String getMethodName() {
    method setMethodName (line 198) | public void setMethodName(String methodName) {
    method getFileName (line 202) | public String getFileName() {
    method setFileName (line 206) | public void setFileName(String fileName) {
    method getLineNumber (line 210) | public int getLineNumber() {
    method setLineNumber (line 214) | public void setLineNumber(int lineNumber) {
    method getMdc (line 218) | public Map<String, String> getMdc() {
    method setMdc (line 222) | public void setMdc(Map<String, String> mdc) {
    method getMdcValue (line 226) | public final String getMdcValue(String key) {
    method getValue (line 233) | public final String getValue(String key) {
    method hashCode (line 252) | @Override
    method equals (line 274) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/PageResult.java
  class PageResult (line 11) | public class PageResult<T> {
    method getList (line 21) | public final List<T> getList() {
    method setList (line 25) | public final PageResult<T> setList(List<T> list) {
    method getPageIndex (line 30) | public final Integer getPageIndex() {
    method setPageIndex (line 34) | public final PageResult<T> setPageIndex(Integer pageIndex) {
    method getPageSize (line 39) | public final Integer getPageSize() {
    method setPageSize (line 43) | public final PageResult<T> setPageSize(Integer pageSize) {
    method getTotal (line 48) | public final Long getTotal() {
    method setTotal (line 52) | public final PageResult<T> setTotal(Long total) {
    type Convertor (line 57) | public static interface Convertor<T, K> {
      method convertFrom (line 59) | K convertFrom(T from) throws BusinessException;
    method convert (line 63) | public <K> PageResult<K> convert(Convertor<T, K> convertor) throws Bus...
    class Scope (line 80) | public static final class Scope {
    method toRecordScope (line 87) | public static Scope toRecordScope(int pageIndex, int pageSize) {
    method toRecordScope (line 91) | public static Scope toRecordScope(int pageIndex, int pageSize, int max...
    method asLikeContent (line 100) | public static String asLikeContent(String fuzzy) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/ServletUtils.java
  class ServletUtils (line 14) | public class ServletUtils {
    method getRequest (line 16) | public static final HttpServletRequest getRequest() {
    method getResponse (line 25) | public static final HttpServletResponse getResponse() {
    method getClientIP (line 40) | public static final String getClientIP() {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/config/RestPackConfiguration.java
  class RestPackConfiguration (line 36) | @PropertySource("classpath:restpack/freemarker.properties")
    method getObjectMapper (line 45) | public static final ObjectMapper getObjectMapper() {
    method createObjectMapper (line 65) | private static final ObjectMapper createObjectMapper() {
    method addConversionConfig (line 106) | public void addConversionConfig() {
    method httpErrorHandler (line 138) | @Bean
    method restPackAspect (line 143) | @Bean
    method restPackAdvice (line 148) | @Bean
    method restPackLogAspect (line 153) | @Bean
    method restPackConfig (line 158) | @Bean
    method httpResultMapper (line 163) | @Bean
    method extendMessageConverters (line 168) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/DateConverter.java
  class DateConverter (line 10) | public class DateConverter implements Converter<String, Date> {
    method convert (line 14) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/ExceptionHolder.java
  class ExceptionHolder (line 3) | public class ExceptionHolder {
    method set (line 7) | public static final void set(Exception e) {
    method get (line 11) | public static final Exception get() {
    method remove (line 15) | public static final void remove() {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/HttpAroundHandler.java
  type HttpAroundHandler (line 13) | public interface HttpAroundHandler {
    method getPriority (line 22) | int getPriority();
    method preHandle (line 32) | HttpResult preHandle(ProceedingJoinPoint point, HttpServletRequest req...
    method postHandle (line 43) | HttpResult postHandle(ProceedingJoinPoint point, HttpServletRequest re...

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/HttpErrorHandler.java
  class HttpErrorHandler (line 23) | @ControllerAdvice
    method handleMissingServletRequestParameterException (line 31) | @ResponseBody
    method handleAuthorizedException (line 39) | @ResponseBody
    method handleAllException (line 46) | @ResponseBody
    method toHttpResult (line 53) | private Object toHttpResult(Exception e, HttpServletRequest request) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/HttpResultMapper.java
  class HttpResultMapper (line 15) | @ConfigurationProperties(prefix = "terran4j.restpack.renaming")
    method getRequestId (line 37) | public String getRequestId() {
    method setRequestId (line 41) | public void setRequestId(String requestId) {
    method getServerTime (line 45) | public String getServerTime() {
    method setServerTime (line 49) | public void setServerTime(String serverTime) {
    method getSpendTime (line 53) | public String getSpendTime() {
    method setSpendTime (line 57) | public void setSpendTime(String spendTime) {
    method getResultCode (line 61) | public String getResultCode() {
    method setResultCode (line 65) | public void setResultCode(String resultCode) {
    method getData (line 69) | public String getData() {
    method setData (line 73) | public void setData(String data) {
    method getMessage (line 77) | public String getMessage() {
    method setMessage (line 81) | public void setMessage(String message) {
    method getProps (line 85) | public String getProps() {
    method setProps (line 89) | public void setProps(String props) {
    method getSuccess (line 93) | public String getSuccess() {
    method setSuccess (line 97) | public void setSuccess(String success) {
    method toMap (line 101) | public Map<String, Object> toMap(HttpResult httpResult) {
    method convert (line 152) | public Object convert(HttpResult httpResult) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/RestPackAdvice.java
  class RestPackAdvice (line 29) | @Component
    method supports (line 36) | @Override
    method beforeBodyWrite (line 41) | @Override
    method setHttpResult (line 77) | void setHttpResult(HttpResult result) {
    method convert (line 94) | BusinessException convert(Throwable e) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/RestPackAspect.java
  class RestPackAspect (line 32) | @Aspect
    method isRestPack (line 43) | public static final boolean isRestPack() {
    method getRequestId (line 47) | public static final String getRequestId() {
    method getBeginTime (line 51) | public static final Long getBeginTime() {
    method getLog (line 55) | public static final Logger getLog() {
    method RestPackAspect (line 62) | public RestPackAspect() {
    method doRequestMapping (line 66) | @Pointcut("@annotation(org.springframework.web.bind.annotation.Request...
    method doGetMapping (line 70) | @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapp...
    method doPostMapping (line 74) | @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMap...
    method doPutMapping (line 78) | @Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapp...
    method doDeleteMapping (line 82) | @Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteM...
    method doPatchMapping (line 86) | @Pointcut("@annotation(org.springframework.web.bind.annotation.PatchMa...
    method doAfter (line 94) | @After(POINTCUT_EXP)
    method doBefore (line 107) | @Before(POINTCUT_EXP)
    method handleThrowing (line 167) | @AfterThrowing(pointcut = POINTCUT_EXP, throwing = "e")
    method generateRequestId (line 177) | public static String generateRequestId() {
    method clearThreadLocal (line 182) | static void clearThreadLocal() {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/RestPackConfig.java
  class RestPackConfig (line 5) | @Service

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/RestPackMessageConverter.java
  class RestPackMessageConverter (line 8) | public class RestPackMessageConverter extends MappingJackson2HttpMessage...
    method RestPackMessageConverter (line 10) | public RestPackMessageConverter(ObjectMapper objectMapper) {
    method canWrite (line 14) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/impl/RestPackUtils.java
  class RestPackUtils (line 15) | public class RestPackUtils {
    method isBasicType (line 48) | public static final boolean isBasicType(Class<?> clazz) {
    method isJavaType (line 52) | public static final boolean isJavaType(Class<?> clazz) {
    method clearIgnoreFields (line 56) | public static void clearIgnoreFields(Object bean) {

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/log/RestPackLogAppender.java
  class RestPackLogAppender (line 16) | public class RestPackLogAppender<E> extends UnsynchronizedAppenderBase<E> {
    method isActive (line 28) | public static boolean isActive() {
    method logEnabled (line 32) | public static void logEnabled(String logPattern) {
    method logClear (line 39) | public static void logClear() {
    method getLogs (line 52) | public static List<String> getLogs() {
    method append (line 76) | @Override

FILE: commons-restpack/src/main/java/com/terran4j/commons/restpack/log/RestPackLogAspect.java
  class RestPackLogAspect (line 22) | @Aspect
    method doLog (line 27) | @Around("@annotation(com.terran4j.commons.restpack.Log)")

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/DemoHttpResultConverter.java
  class DemoHttpResultConverter (line 7) | @Service
    method convert (line 10) | @Override

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/HelloBean.java
  class HelloBean (line 8) | public class HelloBean {
    method getName (line 22) | public final String getName() {
    method setName (line 26) | public final void setName(String name) {
    method getMessage (line 30) | public final String getMessage() {
    method setMessage (line 34) | public final void setMessage(String message) {
    method getTime (line 38) | public final Date getTime() {
    method setTime (line 42) | public final void setTime(Date time) {
    method getDeleted (line 46) | public Boolean getDeleted() {
    method setDeleted (line 50) | public void setDeleted(Boolean deleted) {
    method toString (line 54) | @Override

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/HelloController.java
  class HelloController (line 9) | @Controller
    method hello (line 12) | @RequestMapping("/restpack/hello.html")

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/RestPackDemoApp.java
  class RestPackDemoApp (line 8) | @Slf4j
    method main (line 13) | public static void main(String[] args) {

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/RestPackDemoAspect.java
  class RestPackDemoAspect (line 17) | @Aspect
    method RestPackDemoAspect (line 24) | public RestPackDemoAspect() {
    method httpDemoPackAspect (line 28) | @Pointcut("@annotation(org.springframework.web.bind.annotation.Request...
    method doAfter (line 32) | @After("httpDemoPackAspect()")
    method doBefore (line 36) | @Before("httpDemoPackAspect()")

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/RestPackDemoController.java
  class RestPackDemoController (line 13) | @RestPackController
    method doEcho (line 19) | @Log("doEcho")
    method echo (line 31) | @Log("echo")
    method clientIP (line 40) | @RequestMapping(value = "/client/ip", method = RequestMethod.GET)
    method toDate (line 48) | @Log
    method doVoid (line 62) | @Log
    method hello (line 74) | @Log

FILE: commons-restpack/src/test/java/com/terran4j/demo/restpack/RestPackErrorController.java
  class RestPackErrorController (line 11) | @RestPackController
    method toError (line 21) | @RequestMapping(value = "/be", method = RequestMethod.GET)
    method toError2 (line 33) | @RequestMapping(value = "/re", method = RequestMethod.GET)
    method toErrorByPrimitiveIsNull (line 43) | @RequestMapping(value = "/be/pin", method = RequestMethod.GET)

FILE: commons-restpack/src/test/java/com/terran4j/test/restpack/HttpResultConverterTest.java
  class HttpResultConverterTest (line 16) | @SpringBootTest(
    class MyHttpResult (line 22) | public static class MyHttpResult {
      method getData (line 30) | public Object getData() {
      method setData (line 34) | public void setData(Object data) {
      method getCode (line 38) | public String getCode() {
      method setCode (line 42) | public void setCode(String code) {
      method getMsg (line 46) | public String getMsg() {
      method setMsg (line 50) | public void setMsg(String msg) {
    class MyHttpResultConverter (line 55) | public static class MyHttpResultConverter implements HttpResultConvert...
      method convert (line 57) | @Override
    class RestPackApp (line 67) | @EnableRestPack
      method httpResultConverter (line 71) | @Bean
    method testConvertWithSuccess (line 80) | @Test

FILE: commons-restpack/src/test/java/com/terran4j/test/restpack/HttpResultMapperTest.java
  class HttpResultMapperTest (line 21) | @SpringBootTest(
    class RestPackApp (line 29) | @EnableRestPack
    method testToMapWithSuccess (line 37) | @Test
    method testToMapWithFailure (line 58) | @Test

FILE: commons-restpack/src/test/java/com/terran4j/test/restpack/NoHttpResultConverterTest.java
  class NoHttpResultConverterTest (line 16) | @SpringBootTest(
    class RestPackApp (line 22) | @EnableRestPack
    method testConvertWithSuccess (line 30) | @Test

FILE: commons-restpack/src/test/java/com/terran4j/test/restpack/RestPackTest.java
  class RestPackTest (line 16) | @Slf4j
    class WrapTypeBean (line 20) | public static class WrapTypeBean {
      method WrapTypeBean (line 25) | public WrapTypeBean() {
      method WrapTypeBean (line 28) | public WrapTypeBean(Boolean value) {
      method getValue (line 32) | public Boolean getValue() {
      method setValue (line 36) | public void setValue(Boolean value) {
    method testClearIgnoreFieldOfWrapType (line 42) | @Test
    class BasicTypeBean (line 51) | public static class BasicTypeBean {
      method getValue (line 56) | public boolean getValue() {
      method setValue (line 60) | public void setValue(boolean value) {
    method testClearIgnoreFieldOfBasicType (line 66) | @Test
    class ListBean (line 80) | public static class ListBean {
      method getValue (line 87) | public Integer getValue() {
      method setValue (line 91) | public void setValue(Integer value) {
      method getBeans (line 95) | public List<WrapTypeBean> getBeans() {
      method setBeans (line 99) | public void setBeans(List<WrapTypeBean> beans) {
    method testClearIgnoreFieldOfList (line 104) | @Test
    class MapBean (line 118) | public static class MapBean {
      method getValue (line 125) | public Integer getValue() {
      method setValue (line 129) | public void setValue(Integer value) {
      method getBeans (line 133) | public Map<String, WrapTypeBean> getBeans() {
      method setBeans (line 137) | public void setBeans(Map<String, WrapTypeBean> beans) {
    method testClearIgnoreFieldOfMap (line 142) | @Test

FILE: commons-test/src/main/java/com/terran4j/commons/test/BaseSpringBootTest.java
  class BaseSpringBootTest (line 8) | @RunWith(SpringJUnit4ClassRunner.class)

FILE: commons-test/src/main/java/com/terran4j/commons/test/BaseTestExecutionListener.java
  class BaseTestExecutionListener (line 8) | public class BaseTestExecutionListener implements TestExecutionListener {
    method beforeTestClass (line 10) | @Override
    method prepareTestInstance (line 14) | @Override
    method beforeTestMethod (line 18) | @Override
    method afterTestMethod (line 22) | @Override
    method afterTestClass (line 26) | @Override
    method getSpringBootClasses (line 30) | protected final Class<?>[] getSpringBootClasses(TestContext testContex...

FILE: commons-test/src/main/java/com/terran4j/commons/test/DatabaseInitializer.java
  class DatabaseInitializer (line 30) | public class DatabaseInitializer extends BaseTestExecutionListener {
    method beforeTestMethod (line 37) | @Override
    method truncateTables (line 71) | void truncateTables(Class<?> springBootClass) throws ClassNotFoundExce...
    method removeSQLComments (line 90) | final String removeSQLComments(String sql) {
    method exeSQLs (line 115) | protected void exeSQLs(String sqls) {
    method exeSQL (line 134) | protected void exeSQL(String sql) {
    method exeSQLFile (line 153) | void exeSQLFile(Class<?> nameAsClass) {
    method exeSQLFile (line 158) | void exeSQLFile(Class<?> nameAsClass, String fileName) {

FILE: commons-test/src/main/java/com/terran4j/commons/test/DatabaseTestConfig.java
  class DatabaseTestConfig (line 7) | @Configuration

FILE: commons-test/src/main/java/com/terran4j/commons/test/ExtAssert.java
  class ExtAssert (line 8) | public class ExtAssert {
    method ExtAssert (line 10) | protected ExtAssert() {
    method formatClassAndValue (line 13) | static String formatClassAndValue(Object value, String valueString) {
    method format (line 18) | static String format(String message, Object expected, Object actual) {
    method format (line 33) | static String format(Object expected, Object actual) {
    method assertEquals (line 47) | public static void assertEquals(Date expected, Date actual, long expec...
    method waitFor (line 63) | public static void waitFor(final long millis) {

FILE: commons-test/src/main/java/com/terran4j/commons/test/MockitoInitializer.java
  class MockitoInitializer (line 6) | public class MockitoInitializer extends BaseTestExecutionListener {
    method prepareTestInstance (line 8) | @Override

FILE: commons-test/src/main/java/com/terran4j/commons/test/RedisTestConfig.java
  class RedisTestConfig (line 6) | @Configuration

FILE: commons-test/src/test/java/com/terran4j/commons/test/HelloService.java
  class HelloService (line 3) | public class HelloService {
    method sayHello (line 7) | public String sayHello(String name) {
    method getCount (line 12) | public int getCount() {

FILE: commons-test/src/test/java/com/terran4j/commons/test/MockitoTest.java
  class MockitoTest (line 9) | @TestExecutionListeners({ MockitoInitializer.class })
    method testMock (line 15) | @Test
    method testSpy (line 37) | @Test

FILE: commons-test/src/test/java/com/terran4j/commons/test/TestApp.java
  class TestApp (line 5) | @SpringBootApplication

FILE: commons-util/src/main/java/com/terran4j/commons/util/Arrays.java
  class Arrays (line 3) | public class Arrays {
    method concat (line 11) | public static String[] concat(String[] array1, String[] array2) {
    method safeCopy (line 29) | public static String[] safeCopy(String[] source) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Beans.java
  class Beans (line 26) | public class Beans {
    method toBaseObject (line 55) | private static Object toBaseObject(Class<?> clazz, String value) {
    method upcaseHeadLetter (line 77) | private static String upcaseHeadLetter(String str) {
    method contains (line 81) | private static boolean contains(int value, int flag) {
    method isUpperLetter (line 85) | private static boolean isUpperLetter(char c) {
    method from (line 89) | public static <T> T from(final ValueSource<String, Object> values, Cla...
    method from (line 135) | public static <T> T from(Properties props, Class<T> clazz) {
    method getFieldValue (line 176) | @SuppressWarnings("unchecked")
    method setFieldValue (line 214) | @SuppressWarnings("unchecked")
    method getAllSetMethods (line 234) | public static Map<String, Method> getAllSetMethods(Class<?> clazz) {
    method getFieldNameBySetMethod (line 251) | public static String getFieldNameBySetMethod(Method method) {
    method getSetMethod (line 294) | public static Method getSetMethod(Class<?> clazz, String fieldName) {
    method getGetMethod (line 305) | public static Method getGetMethod(Class<?> clazz, String fieldName) {
    method getSetMethodName (line 316) | public static String getSetMethodName(Class<?> clazz, String fieldName) {
    method isBooleanField (line 327) | private static boolean isBooleanField(Class<?> clazz, String fieldName) {
    method getGetMethodName (line 347) | public static String getGetMethodName(Class<?> clazz, String fieldName) {
    method isBasicType (line 359) | public static boolean isBasicType(Class<?> clazz) {
    method copy (line 375) | public static void copy(Object dest, Object orig) throws BusinessExcep...
    method createBy (line 390) | public static <T> T createBy(Class<T> destClass, Object orig) throws B...

FILE: commons-util/src/main/java/com/terran4j/commons/util/Checker.java
  class Checker (line 9) | public class Checker {
    method checkNotNull (line 11) | public static final void checkNotNull(String value, String key) throws...
    method checkLength (line 18) | public static final String checkLength(String value, int maxLenth, Str...

FILE: commons-util/src/main/java/com/terran4j/commons/util/Classes.java
  class Classes (line 25) | public class Classes {
    method toWrapType (line 52) | public static Class<?> toWrapType(Class<?> clazz) {
    method isMatched (line 63) | private static boolean isMatched(Class<?>[] paramClasses, Object[] par...
    method equals (line 106) | public static boolean equals(Class<?> a, Class<?> b) {
    method getMethod (line 127) | public static Method getMethod(Class<?> clazz, String methodName, Obje...
    method isSuperClass (line 157) | public static boolean isSuperClass(Class<?> child, Class<?> parent) {
    method isInterface (line 180) | public static boolean isInterface(Class<?> clazz, Class<?> interfaceCl...
    method isInterfaceExtends (line 204) | public static final boolean isInterfaceExtends(Class<?> clazz, Class<?...
    method scanClasses (line 239) | public static final Set<Class<?>> scanClasses(Class<?> basePackageClass,
    method scanClasses (line 256) | public static final Set<Class<?>> scanClasses(Class<?> basePackageClas...
    method scanResources (line 326) | public static final Resource[] scanResources(String pathPattern) throw...
    method getTargetClass (line 344) | public static Class<?> getTargetClass(Object object) {
    method getField (line 364) | public static Field getField(String name, Class<?> clazz) {
    method getField (line 391) | public static Field getField(Class<? extends Annotation> annotationCla...
    method getFields (line 411) | public static Field[] getFields(Class<? extends Annotation> annotation...
    method loadFields (line 438) | private static void loadFields(Class<? extends Annotation> annotationC...
    method getAnnotation (line 452) | public static <T extends Annotation> T getAnnotation(Class<?> clazz,
    method getMethod (line 465) | public static Method getMethod(Class<? extends Annotation> annotationC...
    method getMethods (line 482) | public static Method[] getMethods(Class<? extends Annotation> annotati...
    method toIdentify (line 500) | public static final String toIdentify(Method method) {
    method equals (line 516) | public static boolean equals(Method m1, Method m2) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/DateTimes.java
  class DateTimes (line 11) | public class DateTimes {
    method toDateTime (line 21) | public static Date toDateTime(String dateText, String format) {
    method toString (line 27) | public static String toString(Date date) {
    method toString (line 31) | public static String toString(Date date, String format) {
    method toDate (line 36) | public static Date toDate(String dateText) {
    method toDate (line 40) | public static Date toDate(String dateText, String format) {
    method toDate (line 46) | public static String toDate(Date date, String format) {
    method yesterday (line 50) | public static Date yesterday() {
    method shiftDay (line 57) | public static Date shiftDay(int day) {
    method shiftMonth (line 64) | public static Date shiftMonth(int month) {
    method cutHour (line 71) | public static Date cutHour(Date date) {
    method cutDay (line 81) | public static Date cutDay(Date date) {
    method cutMonth (line 92) | public static Date cutMonth(Date date) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Encoding.java
  type Encoding (line 3) | public enum Encoding {
    method Encoding (line 9) | private Encoding(String name){
    method getName (line 13) | public final String getName() {
    method getDefaultEncoding (line 17) | public static Encoding getDefaultEncoding(){

FILE: commons-util/src/main/java/com/terran4j/commons/util/Enums.java
  class Enums (line 8) | public class Enums {
    method getEnumObject (line 10) | public static Object getEnumObject(Class<?> enumType, String name) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Expressions.java
  class Expressions (line 15) | public class Expressions {
    method getExpression (line 23) | public static final Expression getExpression(String expEL) {
    method parse (line 42) | public static final <T> T parse(String el, Map<String, Object> params,...
    method parse (line 48) | public static final Object parse(String el, Map<String, Object> params) {
    method buildContext (line 54) | private static final EvaluationContext buildContext(Map<String, Object...

FILE: commons-util/src/main/java/com/terran4j/commons/util/Files.java
  class Files (line 13) | public class Files {
    method readFile (line 17) | public static String readFile(File file) {
    method writeFile (line 28) | public static void writeFile(String content, File file) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/IOUtils.java
  class IOUtils (line 11) | public class IOUtils {
    method getInputStream (line 17) | public static InputStream getInputStream(Class<?> clazz, String fileNa...
    method getClassPath (line 23) | private static String getClassPath(final Class<?> clazz, String fileNa...
    method copy (line 32) | public static long copy(InputStream input, OutputStream output) throws...
    method getByteArray (line 60) | public static final byte[] getByteArray(InputStream in) {
    method getFileContent (line 79) | public static String getFileContent(File file){
    method setFileContent (line 93) | public static void setFileContent(File file, String content){

FILE: commons-util/src/main/java/com/terran4j/commons/util/IdWorker.java
  class IdWorker (line 18) | public class IdWorker {
    method IdWorker (line 72) | public IdWorker(long workerId, long datacenterId) {
    method nextId (line 91) | public synchronized long nextId() {
    method tilNextMillis (line 131) | protected long tilNextMillis(long lastTimestamp) {
    method timeGen (line 144) | protected long timeGen() {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Jsons.java
  class Jsons (line 20) | public class Jsons {
    method createObjectMapper (line 28) | public static final ObjectMapper createObjectMapper() {
    method getObjectMapper (line 56) | public static final ObjectMapper getObjectMapper() {
    method parseJson (line 60) | public static final JsonElement parseJson(String jsonText) {
    method toJson (line 70) | public static final JsonElement toJson(ConfigElement element) {
    method format (line 113) | public static String format(JsonElement json) {
    method format (line 124) | public static String format(String uglyJsonText) {
    method toMap (line 130) | public static Map<String, Object> toMap(JsonObject json) {
    method toJsonText (line 147) | public static String toJsonText(Object obj) throws JsonProcessingExcep...
    method toObject (line 155) | public static <T> T toObject(String jsonText, Class<T> clazz) throws J...
    method toObject (line 162) | public static Object toObject(JsonElement element) {
    method readJson (line 201) | public static <T> T readJson(Class<T> clazz, File json) throws IOExcep...
    method writeJson (line 212) | public static <T> void writeJson(T object, File file) throws IOExcepti...

FILE: commons-util/src/main/java/com/terran4j/commons/util/Maths.java
  class Maths (line 5) | public class Maths {
    method limitIn (line 16) | public static final int limitIn(int value, Integer min, Integer max) {
    method limitIn (line 30) | public static final long limitIn(long value, Long min, Long max) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Objects.java
  class Objects (line 6) | public class Objects {
    method isSame (line 7) | public static boolean isSame(Object o1, Object o2){
    method isSame (line 13) | public static boolean isSame(Boolean o1, Boolean o2){
    method getField (line 19) | public static Object getField(Object object, String field) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Randoms.java
  class Randoms (line 7) | public class Randoms {
    method getRandom (line 18) | private static SecureRandom getRandom() {
    method createToken (line 31) | public static final String createToken(final int count) {
    method createNumberToken (line 35) | public static final String createNumberToken(final int count) {
    method createToken (line 39) | public static final String createToken(final int count, char[] scope) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Server.java
  class Server (line 8) | public class Server {
    method getInstance (line 14) | private static final Server getInstance() {
    method Server (line 34) | private Server() {
    method getServerIP (line 56) | public static final String getServerIP() {
    method getServerName (line 60) | public static final String getServerName() {

FILE: commons-util/src/main/java/com/terran4j/commons/util/Strings.java
  class Strings (line 33) | public class Strings {
    method toString (line 48) | public static final String toString(Object value) {
    method getString (line 65) | public static String getString(Throwable t) {
    method getString (line 98) | public static String getString(Class<?> clazz, String fileName) {
    method getResourceByPath (line 112) | public static final String getResourceByPath(String path, ClassLoader ...
    method toInputStream (line 140) | public static InputStream toInputStream(String str) {
    method getString (line 160) | public static String getString(InputStream in) {
    method getString (line 171) | public static String getString(InputStream in, Encoding encoding) {
    method getClassPath (line 206) | public static String getClassPath(final Class<?> clazz, String fileNam...
    method format (line 230) | public static String format(String str, final Map<String, Object> args...
    method format (line 244) | public static String format(String str, final Map<String, Object> args) {
    method format (line 256) | public static String format(String str, ValueSource<String, String> va...
    method format (line 276) | public static String format(String str, ValueSource<String, String> va...
    method splitWithTrim (line 329) | public static String[] splitWithTrim(String content) {
    method splitWithTrim (line 340) | public static String[] splitWithTrim(String content, String regex) {
    method splitWithTrim (line 352) | public static String[] splitWithTrim(String content, int limit) {
    method splitWithTrim (line 370) | public static String[] splitWithTrim(String content, String regex, int...
    method toHexString (line 406) | public static String toHexString(byte[] data) {
    method fromHexString (line 427) | public static byte[] fromHexString(String str) {
    method hexToNumber (line 447) | private static final int hexToNumber(int i, String str) {
    method toString (line 457) | public static final String toString(byte[] bytes) {
    method match (line 480) | public static boolean match(String path, String... regexPaths) {
    method toMap (line 505) | public static Map<String, String> toMap(String content, String split, ...
    method formatString (line 536) | public static String formatString(int number, int length){
    method isNull (line 557) | public static boolean isNull(String string){

FILE: commons-util/src/main/java/com/terran4j/commons/util/config/ConfigElement.java
  type ConfigElement (line 11) | public interface ConfigElement extends ValueSource<String, String> {
    method size (line 13) | int size();
    method get (line 15) | default String get(String key) {
    method attr (line 33) | String attr(String attrName);
    method attr (line 35) | default String attr(String attrKey, String defaultValue) {
    method attr (line 43) | default int attr(String attrKey, int defaultValue) {
    method attrAsInt (line 51) | default Integer attrAsInt(String attrKey) {
    method attrAsLong (line 59) | default Long attrAsLong(String attrKey) {
    method attrAsDouble (line 67) | default Double attrAsDouble(String attrKey) {
    method getChildren (line 75) | ConfigElement[] getChildren();
    method getChildren (line 77) | ConfigElement[] getChildren(String elementName);
    method getValue (line 79) | String getValue();
    method attr (line 81) | default boolean attr(String attrKey, boolean defaultValue) {
    method attrAsBoolean (line 89) | default Boolean attrAsBoolean(String attrKey) {
    method getClassLoader (line 97) | ClassLoader getClassLoader();
    method attr (line 99) | default <T> T attr(String attrName, Class<T> clazz) throws BusinessExc...
    method getChildren (line 107) | default <T> List<T> getChildren(String attrKey, Class<T> clazz) throws...
    method asObject (line 126) | <T> T asObject(Class<T> clazz) throws BusinessException;
    method getChild (line 128) | ConfigElement getChild(String eleName) throws BusinessException;
    method getChildText (line 130) | default String getChildText(String eleName) throws BusinessException {
    method getName (line 138) | String getName();
    method attrSet (line 140) | Set<String> attrSet();
    method createObject (line 142) | default Object createObject(String classAttrKey) throws BusinessExcept...
    method asText (line 159) | String asText();

FILE: commons-util/src/main/java/com/terran4j/commons/util/config/JsonConfigElement.java
  class JsonConfigElement (line 11) | public class JsonConfigElement implements ConfigElement {
    method JsonConfigElement (line 21) | public JsonConfigElement(String jsonText) throws BusinessException {
    method JsonConfigElement (line 31) | public JsonConfigElement(JsonElement element, ClassLoader classLoader) {
    method size (line 37) | @Override
    method attr (line 48) | @Override
    method asJsonPrimitive (line 61) | private JsonPrimitive asJsonPrimitive(JsonElement element) {
    method getChildren (line 72) | @Override
    method toConfigElements (line 78) | private ConfigElement[] toConfigElements(JsonArray jsonArray) {
    method asJsonArray (line 94) | private JsonArray asJsonArray(JsonElement element) {
    method asJsonObject (line 105) | private JsonObject asJsonObject(JsonElement element) {
    method getChildren (line 119) | @Override
    method getValue (line 130) | @Override
    method getClassLoader (line 139) | @Override
    method asObject (line 144) | @Override
    method getChild (line 152) | @Override
    method getName (line 165) | @Override
    method attrSet (line 171) | @Override
    method asText (line 191) | @Override

FILE: commons-util/src/main/java/com/terran4j/commons/util/config/XmlConfigElement.java
  class XmlConfigElement (line 26) | public class XmlConfigElement implements ConfigElement {
    method XmlConfigElement (line 34) | public XmlConfigElement(String xmlContent) throws BusinessException {
    method XmlConfigElement (line 54) | public XmlConfigElement(Class<?> clazz, String fileName) throws Busine...
    method XmlConfigElement (line 82) | public XmlConfigElement(Element element) {
    method size (line 88) | @Override
    method attr (line 93) | public String attr(String attriName) {
    method getChildren (line 101) | public ConfigElement[] getChildren() {
    method getChildren (line 120) | public ConfigElement[] getChildren(String eleName) {
    method getValue (line 141) | public String getValue() {
    method getClassLoader (line 167) | @Override
    method asObject (line 172) | @Override
    method getChild (line 177) | public ConfigElement getChild(String eleName) throws BusinessException {
    method getName (line 197) | public String getName() {
    method asText (line 201) | public String asText() {
    method getElement (line 205) | public final Element getElement() {
    method setElement (line 209) | public final void setElement(Element element) {
    method toString (line 213) | public String toString() {
    method attrSet (line 217) | public Set<String> attrSet() {
    method toString (line 231) | private final String toString(int indent) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/error/AuthorizedException.java
  class AuthorizedException (line 5) | public class AuthorizedException extends BusinessException{
    method AuthorizedException (line 6) | public AuthorizedException(String code) {
    method AuthorizedException (line 10) | public AuthorizedException(String code, Object... args) {
    method AuthorizedException (line 14) | public AuthorizedException(String code, Throwable e) {
    method AuthorizedException (line 18) | public AuthorizedException(String code, Locale locale, Throwable e, Ob...
    method AuthorizedException (line 22) | public AuthorizedException(ErrorCode code, Throwable cause) {

FILE: commons-util/src/main/java/com/terran4j/commons/util/error/BusinessException.java
  class BusinessException (line 24) | public class BusinessException extends Exception {
    method getKeys (line 37) | public Enumeration<String> getKeys() { return null; }
    method handleGetObject (line 38) | protected Object handleGetObject(String key) { return null; }
    method toString (line 39) | public String toString() { return "NONEXISTENT_BUNDLE"; }
    method BusinessException (line 46) | public BusinessException(String code) {
    method BusinessException (line 50) | public BusinessException(String code, Object... args) {
    method BusinessException (line 54) | public BusinessException(Str
Condensed preview — 446 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,375K chars).
[
  {
    "path": ".gitignore",
    "chars": 297,
    "preview": "\n/target/\n\n# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tm"
  },
  {
    "path": "LICENSE",
    "chars": 35147,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 1333,
    "preview": "\n## 项目简介\n\n本项目采用 SpringBoot 框架构建,致力于为 SpringBoot 应用程序的开发提升开发效率及编程体验。\n\n本项目由多个子项目组成,每个子项目聚焦解决一个问题。\n这里先简单介绍下这些子项目:\n* [common"
  },
  {
    "path": "build.txt",
    "chars": 875,
    "preview": "\n## 统一修改版本号\nmvn versions:set \"-DnewVersion=1.0.2-SNAPSHOT\"\nmvn versions:commit\n\n## 当版本为 SNAPSHOT 时的测试:\nmvn clean test\n\n#"
  },
  {
    "path": "commons-api2doc/.gitignore",
    "chars": 49,
    "preview": "/target/\n/.settings/\n/.classpath\n/.project\n*.iml\n"
  },
  {
    "path": "commons-api2doc/README.md",
    "chars": 15913,
    "preview": "\n本文介绍一个非常好用的自动化生成 Restful API 文档的工具——Api2Doc\n它基于 SpringBoot ,原理类似于 Swagger2,但比 Swagger2 要简单好用。\n\n此项目已经放到 github 中,需要源码的朋友"
  },
  {
    "path": "commons-api2doc/doc/TODO.md",
    "chars": 808,
    "preview": "\n## 后续开发计划\n\nApi2Doc 项目后续计划要开发的功能如下:\n\n* 参数为对象,参数类型object,可以指出具体类型\n* 可以导出为 html 格式的文档文件,可以离线浏览,\n   支持在页面上手工操作导出,以及程序调用 API"
  },
  {
    "path": "commons-api2doc/doc/aboutCurl.md",
    "chars": 570,
    "preview": "\n## 什么是 curl\ncurl 是一款很强大的 http 命令行工具,可以的向服务端发起 HTTP/HTTPS 请求,\n是一个很方便 HTTP API 测试手段。\n\n## 如何安装 curl \n - 如果是 Linux / MAC 系统"
  },
  {
    "path": "commons-api2doc/pom.xml",
    "chars": 2518,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/Api2DocMocker.java",
    "chars": 540,
    "preview": "package com.terran4j.commons.api2doc;\n\nimport com.terran4j.commons.api2doc.impl.Api2DocObjectFactory;\n\nimport java.util."
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/Api2Doc.java",
    "chars": 932,
    "preview": "package com.terran4j.commons.api2doc.annotations;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.E"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiComment.java",
    "chars": 571,
    "preview": "package com.terran4j.commons.api2doc.annotations;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.E"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiError.java",
    "chars": 483,
    "preview": "package com.terran4j.commons.api2doc.annotations;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.E"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/annotations/ApiErrors.java",
    "chars": 389,
    "preview": "package com.terran4j.commons.api2doc.annotations;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.E"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeConfig.java",
    "chars": 656,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport java.util.List;\n\nimport com.terran4j.commons.api2doc.domain.Api"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeOutput.java",
    "chars": 215,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\npublic interface CodeOutput {\n\n\tvoid writeCodeFile(String fileName, St"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/CodeUtils.java",
    "chars": 477,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport java.util.Set;\n\npublic class CodeUtils {\n\n\tpublic static final "
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/EnumCodeWriter.java",
    "chars": 3188,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport jav"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/FileCodeOutput.java",
    "chars": 554,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport java.io.File;\n\nimport com.terran4j.commons.util.Files;\n\npublic "
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/JavaBeanCodeWriter.java",
    "chars": 5719,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport com.terran4j.commons.api2doc.domain.ApiDataType;\nimport com.ter"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/MemoryCodeOutput.java",
    "chars": 559,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/codewriter/RetrofitCodeWriter.java",
    "chars": 11879,
    "preview": "package com.terran4j.commons.api2doc.codewriter;\n\nimport com.terran4j.commons.api2doc.domain.*;\nimport com.terran4j.comm"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/config/Api2DocConfiguration.java",
    "chars": 832,
    "preview": "package com.terran4j.commons.api2doc.config;\n\nimport com.terran4j.commons.api2doc.codewriter.RetrofitCodeWriter;\nimport "
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/config/EnableApi2Doc.java",
    "chars": 450,
    "preview": "package com.terran4j.commons.api2doc.config;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.Elemen"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/Api2DocController.java",
    "chars": 5435,
    "preview": "package com.terran4j.commons.api2doc.controller;\n\nimport com.terran4j.commons.api2doc.domain.ApiDocObject;\nimport com.te"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiEntry.java",
    "chars": 968,
    "preview": "package com.terran4j.commons.api2doc.controller;\n\npublic class ApiEntry {\n\n    private String key;\n\n    private String v"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiInfo.java",
    "chars": 2219,
    "preview": "package com.terran4j.commons.api2doc.controller;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class ApiInfo "
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/ApiMetaController.java",
    "chars": 1070,
    "preview": "package com.terran4j.commons.api2doc.controller;\n\nimport com.terran4j.commons.api2doc.meta.ApiMetaService;\nimport com.te"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/controller/MenuData.java",
    "chars": 1850,
    "preview": "package com.terran4j.commons.api2doc.controller;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.te"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDataType.java",
    "chars": 6297,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport com.fasterxml.jackson.databind.JsonMappingException;\nimport com.fas"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocObject.java",
    "chars": 3020,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport com.terran4j.commons.api2doc.impl.Api2DocObjectFactory;\nimport com."
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiDocUtils.java",
    "chars": 592,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport org.springframework.util.StringUtils;\n\nimport com.terran4j.commons."
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiErrorObject.java",
    "chars": 97,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\npublic class ApiErrorObject extends ApiObject {\n\n}\n"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiFolderObject.java",
    "chars": 1868,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport com.terran4j.commons.util.value.KeyedList;\nimport org.springframewo"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiObject.java",
    "chars": 1773,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamLocation.java",
    "chars": 5850,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport org.springframework.util.StringUtils;\nimport org.springframework.we"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiParamObject.java",
    "chars": 1135,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\npublic class ApiParamObject extends ApiObject {\n\t\n\tprivate boolean require"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/ApiResultObject.java",
    "chars": 11292,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/domain/DateConverter.java",
    "chars": 765,
    "preview": "package com.terran4j.commons.api2doc.domain;\n\nimport java.util.Date;\n\npublic class DateConverter {\n\n    public static bo"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocCollector.java",
    "chars": 20231,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocObjectFactory.java",
    "chars": 11321,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.Api2DocMocker;\nimport com.terran4j.commo"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocProperties.java",
    "chars": 899,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.spring"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocService.java",
    "chars": 1915,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.domain.ApiDocObject;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/Api2DocUtils.java",
    "chars": 7591,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.terran4j.comm"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ApiCommentUtils.java",
    "chars": 5070,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.annotations.ApiComment;\nimport com.terra"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/ClasspathFreeMarker.java",
    "chars": 2186,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/CurlBuilder.java",
    "chars": 6406,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.domain.ApiDocObject;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocMenuBuilder.java",
    "chars": 3688,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.controller.MenuData;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/DocPageBuilder.java",
    "chars": 7221,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport com.terran4j.commons.api2doc.domain.ApiDocObject;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/FlexibleString.java",
    "chars": 1877,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\n/**\n * 将空串视为 null\n * 能转成 html 格式。\n */\npublic class FlexibleString {\n\n    pri"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/impl/MappingMethod.java",
    "chars": 6094,
    "preview": "package com.terran4j.commons.api2doc.impl;\n\nimport org.springframework.web.bind.annotation.*;\n\nimport java.lang.annotati"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ApiMetaService.java",
    "chars": 4578,
    "preview": "package com.terran4j.commons.api2doc.meta;\n\nimport com.terran4j.commons.api2doc.controller.ApiEntry;\nimport com.terran4j"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ClassMeta.java",
    "chars": 826,
    "preview": "package com.terran4j.commons.api2doc.meta;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ClassMeta {"
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/MethodMeta.java",
    "chars": 1218,
    "preview": "package com.terran4j.commons.api2doc.meta;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MethodMeta "
  },
  {
    "path": "commons-api2doc/src/main/java/com/terran4j/commons/api2doc/meta/ParamMeta.java",
    "chars": 1218,
    "preview": "package com.terran4j.commons.api2doc.meta;\n\nimport com.terran4j.commons.api2doc.domain.ApiDataType;\nimport com.terran4j."
  },
  {
    "path": "commons-api2doc/src/main/resources/api2doc/welcome.md",
    "chars": 16,
    "preview": "\n欢迎使用 Api2Doc !\n"
  },
  {
    "path": "commons-api2doc/src/main/resources/com/terran4j/commons/api2doc/codewriter/bean.java.ftl",
    "chars": 710,
    "preview": "<#if config.pkgName??>\npackage ${config.pkgName};\n</#if>\n\n<#list imports as import>\nimport ${import};\n</#list>\n\n/**\n<#if"
  },
  {
    "path": "commons-api2doc/src/main/resources/com/terran4j/commons/api2doc/codewriter/enum.java.ftl",
    "chars": 264,
    "preview": "<#if config.pkgName??>\npackage ${config.pkgName};\n</#if>\n\n/**\n<#if config.declaredComment??>\n * ${config.declaredComment"
  },
  {
    "path": "commons-api2doc/src/main/resources/com/terran4j/commons/api2doc/codewriter/retrofit.java.ftl",
    "chars": 791,
    "preview": "<#if config.pkgName??>\npackage ${config.pkgName};\n</#if>\n\nimport retrofit2.Call;\nimport retrofit2.http.*;\n\n<#list import"
  },
  {
    "path": "commons-api2doc/src/main/resources/com/terran4j/commons/api2doc/impl/doc.md.ftl",
    "chars": 1829,
    "preview": "**API标识**\n- ${folder.id}-${doc.id}\n\n<#if doc.comment?? && doc.comment!=\"\">\n**API简介** \n- ${doc.comment}\n</#if>\n\n<br/>\n\n<#"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/css/doc.less",
    "chars": 1359,
    "preview": "//////////////////////////    整个 html、 body 及公共的样式   /////////////////\nhtml {\n  overflow-y: scroll;\n}\n\n@media only scree"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/css/home.less",
    "chars": 1863,
    "preview": "\n// 菜单栏背景的颜色。\n@menu-color: white;\n\n// 分隔线的颜色:\n@split-color: rgba(0,0,0,.07);\n\nhtml {\n  overflow: hidden;\n}\n\n.doc-app {\n "
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/css/md.less",
    "chars": 3148,
    "preview": "\n////////////////////////////////    通用样式    //////////////////////\n\np, blockquote, ul, ol, dl, li, table, pre {\n  margi"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/css/test.less",
    "chars": 1854,
    "preview": "@left-space: 1rem;\n@font-base-size: 1rem;\n\nh2 {\n  margin-left: @left-space;\n}\n\n//h3 {\n//  margin-left: @left-space;\n//}\n"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/flexible-lite/flexible-lite-1.0.js",
    "chars": 1346,
    "preview": "/**\n * @param designWidth:  设计稿的实际宽度值,需要根据实际设置\n */\nfunction flex(designWidth) {\n    var doc = document,\n        win = wi"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/less/less-1.7.0.js",
    "chars": 280172,
    "preview": "/*! \n * LESS - Leaner CSS v1.7.0 \n * http://lesscss.org \n * \n * Copyright (c) 2009-2014, Alexis Sellier <self@cloudhead."
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/test.html",
    "chars": 7639,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Api2Doc 接口测试</title>\n\n    <!--\n        使用 rem 布局,使 H5 页面能适配不同设备屏幕尺寸\n        fle"
  },
  {
    "path": "commons-api2doc/src/main/resources/static/api2doc/vue/vue-2.5.10.js",
    "chars": 283925,
    "preview": "/*!\n * Vue.js v2.5.10\n * (c) 2014-2017 Evan You\n * Released under the MIT License.\n */\n(function (global, factory) {\n\tty"
  },
  {
    "path": "commons-api2doc/src/main/resources/templates/api2doc/doc.ftl",
    "chars": 1470,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<#if title ??>\n    <title>${title}</title>\n</#if>\n    <!--\n        使用 rem 布局,使 H5 页面能适配不同设"
  },
  {
    "path": "commons-api2doc/src/main/resources/templates/api2doc/home.ftl",
    "chars": 3240,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <title>${title}</title>\n    <!--\n        使用 rem 布局,使 H5 页面能适配不同设备屏幕尺寸\n        flexible"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/Api2DocDemoApp.java",
    "chars": 711,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.config.EnableApi2Doc;\nimport com.terran4j.common"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/CodeGenerator.java",
    "chars": 1849,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.codewriter.CodeConfig;\nimport com.terran4j.commo"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/FileInfo.java",
    "chars": 1175,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.util.Strings;\nimport org.springframework.web.multipart.M"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowMappingController.java",
    "chars": 2707,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowParamController.java",
    "chars": 2754,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/ShowResultController.java",
    "chars": 1699,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.Api2DocMocker;\nimport com.terran4j.commons.api2d"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/User.java",
    "chars": 1735,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.ApiComment;\nimport com.terran4j.comm"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController.java",
    "chars": 2230,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.Api2DocMocker;\nimport com.terran4j.commons.api2d"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController1.java",
    "chars": 863,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController2.java",
    "chars": 1763,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserController3.java",
    "chars": 792,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport org.springframework."
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserGroup.java",
    "chars": 467,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.terran4j.commons.api2"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/demo/api2doc/UserType.java",
    "chars": 190,
    "preview": "package com.terran4j.demo.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.ApiComment;\n\npublic enum UserType {\n"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocCollectorTest.java",
    "chars": 2603,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocObjectFactoryTest.java",
    "chars": 3305,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.ApiComment;\nimport com.terran4j.comm"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/Api2DocUtilsTest.java",
    "chars": 3072,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ApiCommentUtilsTest.java",
    "chars": 3262,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ApiResultObjectTest.java",
    "chars": 8167,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/Application.java",
    "chars": 233,
    "preview": "package com.terran4j.test.api2doc;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\nimport com.ter"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/BaseApi2DocTest.java",
    "chars": 998,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.domain.ApiDocObject;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/CurlBuilderTest.java",
    "chars": 3376,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/JavaBeanCodeWriterTest.java",
    "chars": 2332,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.lang.reflect.Method;\nimport java.util.Date;\nimport java.util.Map;\nimport"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/MyBean.java",
    "chars": 1468,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashSet;\nimport "
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnMethod.java",
    "chars": 2075,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.lang.reflect.Method;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nim"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnParam.java",
    "chars": 2746,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnSeeClass.java",
    "chars": 3704,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseApiCommentOnSeeClassLoop.java",
    "chars": 3729,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseEnumTest.java",
    "chars": 1350,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.lang.reflect.Method;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nim"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ParseListBeanTest.java",
    "chars": 3182,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ResultSourceTypeTest.java",
    "chars": 1069,
    "preview": "package com.terran4j.test.api2doc;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n"
  },
  {
    "path": "commons-api2doc/src/test/java/com/terran4j/test/api2doc/ToMockResultTest.java",
    "chars": 2137,
    "preview": "package com.terran4j.test.api2doc;\n\nimport com.terran4j.commons.api2doc.annotations.Api2Doc;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/demo3/1-项目简介.md",
    "chars": 9,
    "preview": "\n***简介***"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/demo3/11-接口1的补充说明.md",
    "chars": 11,
    "preview": "\n***注意事项***"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/demo3/2-技术架构.md",
    "chars": 12,
    "preview": "\n***关于本项目***"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/demo3/21-接口2的补充说明.md",
    "chars": 9,
    "preview": "\n***附录***"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/demo3/3-应用场景.md",
    "chars": 11,
    "preview": "\n***必要条件***"
  },
  {
    "path": "commons-api2doc/src/test/resources/api2doc/welcome.md",
    "chars": 143,
    "preview": "\n\n## 目录\n\n* 项目背景\n* Api2Doc 简介\n* 引入 Api2Doc 依赖\n* 启用 Api2Doc 服务\n* 给 Controller 类上添加文档注解\n* 给文档菜单项排序\n* 补充自定义文档\n* 定制欢迎页\n* 定制标题"
  },
  {
    "path": "commons-api2doc/src/test/resources/application.yml",
    "chars": 257,
    "preview": "\n# 本地环境\napi2doc:\n  title: Api2Doc示例项目——接口文档\n  icon: https://spring.io/img/homepage/icon-spring-framework.svg\n\nserver:\n  "
  },
  {
    "path": "commons-armq/.gitignore",
    "chars": 21,
    "preview": "\n*.iml\n*.log\n/target/"
  },
  {
    "path": "commons-armq/pom.xml",
    "chars": 1866,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"ht"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/ArmqConfig.java",
    "chars": 1146,
    "preview": "package com.terran4j.commons.armq;\n\nimport com.aliyun.mq.http.MQClient;\nimport com.terran4j.commons.armq.impl.MessageSer"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/ConsumerConfig.java",
    "chars": 673,
    "preview": "package com.terran4j.commons.armq;\n\nimport lombok.Data;\n\n@Data\npublic class ConsumerConfig {\n\n    /**\n     * 每次拉取多少条消息。\n"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/MessageConsumer.java",
    "chars": 343,
    "preview": "package com.terran4j.commons.armq;\n\nimport com.terran4j.commons.util.error.BusinessException;\n\npublic interface MessageC"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/MessageEntity.java",
    "chars": 486,
    "preview": "package com.terran4j.commons.armq;\n\nimport java.lang.annotation.*;\n\n/**\n * 定义一个 Topic 的实体类:<br>\n * 此 Topic 名称即类的 SimpleN"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/MessageService.java",
    "chars": 1393,
    "preview": "package com.terran4j.commons.armq;\n\nimport com.terran4j.commons.util.error.BusinessException;\n\npublic interface MessageS"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageConsumerTask.java",
    "chars": 4244,
    "preview": "package com.terran4j.commons.armq.impl;\n\nimport com.aliyun.mq.http.MQConsumer;\nimport com.aliyun.mq.http.common.AckMessa"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageConsumerTransfer.java",
    "chars": 3224,
    "preview": "package com.terran4j.commons.armq.impl;\n\nimport com.aliyun.mq.http.MQConsumer;\nimport com.terran4j.commons.armq.Consumer"
  },
  {
    "path": "commons-armq/src/main/java/com/terran4j/commons/armq/impl/MessageServiceImpl.java",
    "chars": 8010,
    "preview": "package com.terran4j.commons.armq.impl;\n\nimport com.aliyun.mq.http.MQClient;\nimport com.aliyun.mq.http.MQConsumer;\nimpor"
  },
  {
    "path": "commons-armq/src/test/java/com/terran4j/commons/test/armq/ArmqTestApp.java",
    "chars": 288,
    "preview": "package com.terran4j.commons.test.armq;\n\nimport com.terran4j.commons.armq.ArmqConfig;\nimport org.springframework.boot.au"
  },
  {
    "path": "commons-armq/src/test/java/com/terran4j/commons/test/armq/Normal.java",
    "chars": 350,
    "preview": "package com.terran4j.commons.test.armq;\n\nimport com.terran4j.commons.armq.MessageEntity;\nimport lombok.Data;\nimport lomb"
  },
  {
    "path": "commons-armq/src/test/java/com/terran4j/commons/test/armq/NormalTopicTest.java",
    "chars": 2492,
    "preview": "package com.terran4j.commons.test.armq;\n\nimport com.terran4j.commons.armq.ArmqConfig;\nimport com.terran4j.commons.armq.M"
  },
  {
    "path": "commons-armq/src/test/java/com/terran4j/commons/test/armq/Producer.java",
    "chars": 2776,
    "preview": "package com.terran4j.commons.test.armq;\n\nimport com.aliyun.mq.http.MQClient;\nimport com.aliyun.mq.http.MQProducer;\nimpor"
  },
  {
    "path": "commons-armq/src/test/java/com/terran4j/commons/test/armq/SendTest.java",
    "chars": 2724,
    "preview": "//package com.terran4j.commons.test.mmq;\n//\n//import com.aliyun.openservices.ons.api.*;\n//\n//import java.io.UnsupportedE"
  },
  {
    "path": "commons-armq/src/test/resources/.gitignore",
    "chars": 17,
    "preview": "\napplication.yml\n"
  },
  {
    "path": "commons-dsql/.gitignore",
    "chars": 48,
    "preview": "/target/\n/.classpath\n/.project\n/.settings/\n*.iml"
  },
  {
    "path": "commons-dsql/README.md",
    "chars": 18180,
    "preview": "\n\n## 目录\n\n* 项目背景\n* DSQL 简介\n* 示例程序介绍\n* 引入 DSQL 依赖\n* 定义实体类\n* 编写 JpaRepository\n* 编写 DsqlRepository\n* 省略 @Param 注解\n* 返回结果的类型映"
  },
  {
    "path": "commons-dsql/pom.xml",
    "chars": 1532,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlExecutor.java",
    "chars": 880,
    "preview": "package com.terran4j.commons.dsql;\n\nimport com.terran4j.commons.dsql.impl.SqlInfo;\nimport com.terran4j.commons.util.erro"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlModifying.java",
    "chars": 201,
    "preview": "package com.terran4j.commons.dsql;\n\nimport java.lang.annotation.*;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementT"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlQuery.java",
    "chars": 197,
    "preview": "package com.terran4j.commons.dsql;\n\nimport java.lang.annotation.*;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementT"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/DsqlRepository.java",
    "chars": 129,
    "preview": "package com.terran4j.commons.dsql;\n\n/**\n * 动态 SQL Repository 接口。\n * @param <T> 表对应的类\n */\npublic interface DsqlRepository"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/EnableDsqlRepositories.java",
    "chars": 442,
    "preview": "package com.terran4j.commons.dsql;\n\nimport com.terran4j.commons.dsql.impl.DsqlRepositoryConfigRegistrar;\nimport org.spri"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/QueryBean.java",
    "chars": 686,
    "preview": "package com.terran4j.commons.dsql;\n\nimport com.terran4j.commons.util.Strings;\n\npublic class QueryBean {\n\n    public stat"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/config/DsqlConfiguration.java",
    "chars": 332,
    "preview": "package com.terran4j.commons.dsql.config;\n\nimport com.terran4j.commons.dsql.impl.DsqlExecutorImpl;\nimport org.springfram"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/CompositeBeanRowMapper.java",
    "chars": 3081,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframe"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlBuilder.java",
    "chars": 5574,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport com.terran4j.commons.util.Encoding;\nimport com.terran4j.commons.util.err"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlExecutorImpl.java",
    "chars": 1943,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport com.terran4j.commons.dsql.DsqlExecutor;\nimport com.terran4j.commons.util"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryBeanFactory.java",
    "chars": 803,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.bea"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryConfigRegistrar.java",
    "chars": 6483,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport com.terran4j.commons.dsql.DsqlExecutor;\nimport com.terran4j.commons.dsql"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/DsqlRepositoryProxy.java",
    "chars": 8952,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport com.terran4j.commons.dsql.DsqlExecutor;\nimport com.terran4j.commons.dsql"
  },
  {
    "path": "commons-dsql/src/main/java/com/terran4j/commons/dsql/impl/SqlInfo.java",
    "chars": 1877,
    "preview": "package com.terran4j.commons.dsql.impl;\n\nimport com.terran4j.commons.util.Expressions;\nimport com.terran4j.commons.util."
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/Address.java",
    "chars": 1166,
    "preview": "package com.terran4j.demo.dsql;\n\nimport javax.persistence.*;\n\n@Entity(name = \"demo_address\")\n@Table(indexes = {\n\t\t@Index"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDAO.java",
    "chars": 166,
    "preview": "package com.terran4j.demo.dsql;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\npublic interface Address"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDistance.java",
    "chars": 585,
    "preview": "package com.terran4j.demo.dsql;\n\nimport com.terran4j.commons.util.Strings;\n\npublic class AddressDistance {\n\n    // 位置记录\n"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressDistanceDAO.java",
    "chars": 1083,
    "preview": "package com.terran4j.demo.dsql;\n\nimport com.terran4j.commons.dsql.DsqlModifying;\nimport com.terran4j.commons.dsql.DsqlQu"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/AddressQuery.java",
    "chars": 949,
    "preview": "package com.terran4j.demo.dsql;\n\nimport com.terran4j.commons.util.Strings;\n\npublic class AddressQuery {\n\n    private Dou"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-count.sql.ftl",
    "chars": 354,
    "preview": "\nSELECT count(*) from (\n    SELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n        POW(SIN(( @{lat} * PI() / 180 - lat * PI()"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-delete-nearest.sql.ftl",
    "chars": 438,
    "preview": "\nDELETE from demo_address\nWHERE id IN (\n    SELECT t.id FROM (\n        SELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n       "
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-list.sql.ftl",
    "chars": 410,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{args.lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS("
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-nearest-2.sql.ftl",
    "chars": 302,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{arg0} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS( @{a"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-nearest.sql.ftl",
    "chars": 299,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS( @{la"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/address-update-nearest.sql.ftl",
    "chars": 454,
    "preview": "\nUPDATE demo_address SET `name` = @{name}\nWHERE id IN (\n    SELECT t.id FROM (\n        SELECT *, ROUND(6378.137 * 2 * AS"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/appdsql/DsqlDemoApplication.java",
    "chars": 4488,
    "preview": "package com.terran4j.demo.dsql.appdsql;\n\nimport com.terran4j.commons.dsql.EnableDsqlRepositories;\nimport com.terran4j.co"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/demo/dsql/appjpa/JpaDemoApplication.java",
    "chars": 2278,
    "preview": "package com.terran4j.demo.dsql.appjpa;\n\nimport com.terran4j.commons.test.DatabaseTestConfig;\nimport com.terran4j.commons"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/BaseDsqlTest.java",
    "chars": 2753,
    "preview": "package com.terran4j.test.dsql;\n\nimport com.terran4j.commons.dsql.DsqlExecutor;\nimport com.terran4j.commons.dsql.EnableD"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlAutoTest.java",
    "chars": 1857,
    "preview": "package com.terran4j.test.dsql;\n\nimport com.terran4j.test.dsql.dao.Location;\nimport com.terran4j.test.dsql.dao.LocationQ"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlModifyingTest.java",
    "chars": 1851,
    "preview": "package com.terran4j.test.dsql;\n\nimport com.terran4j.test.dsql.dao1.LocationDsqlDAO;\nimport com.terran4j.test.dsql.dao2."
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/DsqlQueryTest.java",
    "chars": 2965,
    "preview": "package com.terran4j.test.dsql;\n\nimport com.terran4j.test.dsql.dao.*;\nimport com.terran4j.test.dsql.dao2.LocationDistanc"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao/Location.java",
    "chars": 1140,
    "preview": "package com.terran4j.test.dsql.dao;\n\nimport javax.persistence.*;\n\n@Entity(name = \"test_location\")\n@Table(indexes = { //\n"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao/LocationDAO.java",
    "chars": 172,
    "preview": "package com.terran4j.test.dsql.dao;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\npublic interface Loc"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao/LocationQuery.java",
    "chars": 566,
    "preview": "package com.terran4j.test.dsql.dao;\n\npublic class LocationQuery {\n\n    private Double lat;\n\n    private Double lon;\n\n   "
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao1/LocationDsqlDAO.java",
    "chars": 582,
    "preview": "package com.terran4j.test.dsql.dao1;\n\nimport com.terran4j.commons.dsql.DsqlRepository;\nimport com.terran4j.commons.dsql."
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao1/delete-nearest.sql.ftl",
    "chars": 440,
    "preview": "\nDELETE from test_location\nWHERE id IN (\n    SELECT t.id FROM (\n        SELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n      "
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao1/update-nearest.sql.ftl",
    "chars": 456,
    "preview": "\nUPDATE test_location SET `name` = @{name}\nWHERE id IN (\n    SELECT t.id FROM (\n        SELECT *, ROUND(6378.137 * 2 * A"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/LocationDistance.java",
    "chars": 606,
    "preview": "package com.terran4j.test.dsql.dao2;\n\nimport com.terran4j.commons.util.Strings;\nimport com.terran4j.test.dsql.dao.Locati"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/LocationDistanceDAO.java",
    "chars": 549,
    "preview": "package com.terran4j.test.dsql.dao2;\n\nimport com.terran4j.commons.dsql.DsqlQuery;\nimport com.terran4j.commons.dsql.DsqlR"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/location-nearest.sql.ftl",
    "chars": 300,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS( @{la"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao2/locations.sql.ftl",
    "chars": 342,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{args.lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS("
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/DistancedLocation.java",
    "chars": 314,
    "preview": "package com.terran4j.test.dsql.dao3;\n\nimport com.terran4j.test.dsql.dao.Location;\n\npublic class DistancedLocation extend"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/DistancedLocationDAO.java",
    "chars": 445,
    "preview": "package com.terran4j.test.dsql.dao3;\n\nimport com.terran4j.commons.dsql.DsqlQuery;\nimport com.terran4j.commons.dsql.DsqlR"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/location-count.sql.ftl",
    "chars": 361,
    "preview": "\nSELECT count(*) from (\n    SELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n        POW(SIN(( @{args.lat} * PI() / 180 - lat *"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao3/locations.sql.ftl",
    "chars": 342,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{args.lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS("
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao4/LocationAutoDAO.java",
    "chars": 517,
    "preview": "package com.terran4j.test.dsql.dao4;\n\nimport com.terran4j.commons.dsql.DsqlRepository;\nimport com.terran4j.test.dsql.dao"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao4/countLocation.sql.ftl",
    "chars": 361,
    "preview": "\nSELECT count(*) from (\n    SELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n        POW(SIN(( @{args.lat} * PI() / 180 - lat *"
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao4/getLocations.sql.ftl",
    "chars": 342,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{args.lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS("
  },
  {
    "path": "commons-dsql/src/test/java/com/terran4j/test/dsql/dao4/getNearestLocation.sql.ftl",
    "chars": 300,
    "preview": "\nSELECT *, ROUND(6378.137 * 2 * ASIN(SQRT(\n    POW(SIN(( @{lat} * PI() / 180 - lat * PI() / 180) / 2),2)\n    + COS( @{la"
  },
  {
    "path": "commons-hedis/.gitignore",
    "chars": 37,
    "preview": "/target/\n/.classpath\n/.project\n*.iml\n"
  },
  {
    "path": "commons-hedis/README.md",
    "chars": 10374,
    "preview": "\n本项目基于 Redis 提供两个常用的功能:\n1. 分布式锁;\n2. 轻量级分布式任务调度;\n\n此项目已经放到 github 中,需要源码的朋友请点击\n[这里](https://github.com/terran4j/commons/tr"
  },
  {
    "path": "commons-hedis/pom.xml",
    "chars": 2093,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/CacheService.java",
    "chars": 2073,
    "preview": "package com.terran4j.commons.hedis.cache;\n\nimport java.util.Map;\n\nimport com.terran4j.commons.util.error.BusinessExcepti"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/JedisCacheService.java",
    "chars": 6804,
    "preview": "package com.terran4j.commons.hedis.cache;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.apache.commons.la"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/cache/RedisTemplateCacheService.java",
    "chars": 6831,
    "preview": "package com.terran4j.commons.hedis.cache;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.T"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/config/EnableHedis.java",
    "chars": 603,
    "preview": "package com.terran4j.commons.hedis.config;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementT"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/config/HedisConfiguration.java",
    "chars": 9028,
    "preview": "package com.terran4j.commons.hedis.config;\n\nimport com.fasterxml.jackson.annotation.JsonAutoDetect;\nimport com.fasterxml"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/DScheduling.java",
    "chars": 1086,
    "preview": "package com.terran4j.commons.hedis.dschedule;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.Reten"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/DSchedulingAspect.java",
    "chars": 12995,
    "preview": "package com.terran4j.commons.hedis.dschedule;\n\nimport com.terran4j.commons.hedis.cache.CacheService;\nimport com.terran4j"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/JobExeInfo.java",
    "chars": 2282,
    "preview": "package com.terran4j.commons.hedis.dschedule;\n\nimport com.terran4j.commons.util.Strings;\n\npublic class JobExeInfo {\n\n\tpr"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dschedule/ScheduleContext.java",
    "chars": 553,
    "preview": "package com.terran4j.commons.hedis.dschedule;\n\nimport static java.lang.annotation.ElementType.FIELD;\nimport static java."
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/DSynchArgs.java",
    "chars": 630,
    "preview": "package com.terran4j.commons.hedis.dsyn;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class DSynchArgs {\n\n\tp"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/DSynchronized.java",
    "chars": 1699,
    "preview": "package com.terran4j.commons.hedis.dsyn;\n\nimport static java.lang.annotation.ElementType.METHOD;\nimport static java.lang"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/DSynchronizedAspect.java",
    "chars": 7542,
    "preview": "package com.terran4j.commons.hedis.dsyn;\n\nimport com.terran4j.commons.util.Classes;\nimport com.terran4j.commons.util.err"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/commons/hedis/dsyn/Server.java",
    "chars": 243,
    "preview": "package com.terran4j.commons.hedis.dsyn;\n\nimport java.util.UUID;\n\npublic class Server {\n\n    private static final String"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/mock/hedis/MockCacheService.java",
    "chars": 2189,
    "preview": "package com.terran4j.mock.hedis;\n\nimport com.terran4j.commons.hedis.cache.CacheService;\nimport com.terran4j.commons.util"
  },
  {
    "path": "commons-hedis/src/main/java/com/terran4j/mock/hedis/MockHedisConfig.java",
    "chars": 502,
    "preview": "package com.terran4j.mock.hedis;\n\nimport com.terran4j.commons.hedis.cache.CacheService;\nimport com.terran4j.commons.util"
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/CountService.java",
    "chars": 1385,
    "preview": "package com.terran4j.demo.hedis;\n\nimport com.terran4j.commons.hedis.cache.CacheService;\nimport com.terran4j.commons.hedi"
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/DSynchronizedCountService.java",
    "chars": 932,
    "preview": "package com.terran4j.demo.hedis;\n\nimport java.util.Random;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimp"
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/DemoCacheService.java",
    "chars": 1027,
    "preview": "package com.terran4j.demo.hedis;\n\nimport com.terran4j.commons.hedis.cache.CacheService;\nimport org.slf4j.Logger;\nimport "
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/HedisDemoApp.java",
    "chars": 442,
    "preview": "package com.terran4j.demo.hedis;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.aut"
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/LoopIncrementJob.java",
    "chars": 807,
    "preview": "package com.terran4j.demo.hedis;\n\nimport com.terran4j.commons.hedis.dschedule.DScheduling;\nimport org.slf4j.Logger;\nimpo"
  },
  {
    "path": "commons-hedis/src/test/java/com/terran4j/demo/hedis/User.java",
    "chars": 855,
    "preview": "package com.terran4j.demo.hedis;\n\nimport com.terran4j.commons.util.Strings;\n\nimport java.util.Date;\n\npublic class User {"
  }
]

// ... and 246 more files (download for full content)

About this extraction

This page contains the full source code of the terran4j/commons GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 446 files (2.1 MB), approximately 565.3k tokens, and a symbol index with 3080 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!