From 3dc4a1b5187ab7a7f184938fd491258577ef74d1 Mon Sep 17 00:00:00 2001 From: Alex_libo Date: Fri, 19 Apr 2019 21:28:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96toolbox=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=E9=A1=B9=E7=9B=AE=E4=BB=A3=E7=A0=81=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E6=95=B4=E4=BD=93=E7=BB=84=E4=BB=B6=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coffice-toolbox-apidoc/pom.xml | 77 + .../hyts/apidoc/analysis/AnalysisEngine.java | 61 + .../apidoc/analysis/AnalysisTemplate.java | 171 + .../com/hyts/apidoc/base/AbstractScanner.java | 44 + .../hyts/apidoc/base/AnnotationDocConfig.java | 27 + .../com/hyts/apidoc/base/BaseApiParser.java | 43 + .../com/hyts/apidoc/bean/ScanBaseObject.java | 60 + .../com/hyts/apidoc/bean/ScanExtObject.java | 76 + .../hyts/apidoc/bean/ScanResultObject.java | 104 + .../hyts/apidoc/config/AnalysisConfig.java | 106 + .../com/hyts/apidoc/config/ParseDocType.java | 35 + .../java/com/hyts/apidoc/config/ScanRule.java | 35 + .../hyts/apidoc/config/ScanRuleConfig.java | 45 + .../com/hyts/apidoc/error/ApiDocError.java | 68 + .../hyts/apidoc/javadoc/JavaDocHandler.java | 56 + .../hyts/apidoc/javadoc/JavaDocSupport.java | 58 + .../com/hyts/apidoc/model/ApiDefination.java | 195 + .../java/com/hyts/apidoc/model/ApiDoc.java | 221 + .../java/com/hyts/apidoc/model/ApiParam.java | 129 + .../apidoc/parser/AnnotationApiParser.java | 48 + .../hyts/apidoc/parser/JavaDocApiParser.java | 98 + .../hyts/apidoc/parser/SwaggerApiParser.java | 48 + .../com/hyts/apidoc/scanner/JarScanner.java | 100 + .../java/com/hyts/apidoc/scanner/Scanner.java | 111 + .../hyts/apidoc/scanner/SourceScanner.java | 99 + .../apidoc/scanner/filter/ClassFilter.java | 47 + .../scanner/filter/ClassNameFilter.java | 80 + .../apidoc/scanner/help/AnnotationHelper.java | 85 + .../hyts/apidoc/scanner/help/ClassHelper.java | 138 + .../hyts/apidoc/scanner/help/ScanHelper.java | 138 + .../hyts/apidoc/servlet/ApiDocServlet.java | 202 + .../springboot/ApiDocConfiguration.java | 53 + .../ApiDocServletConfiguration.java | 38 + .../apidoc/template/TemplateDataHandler.java | 205 + .../apidoc/template/TemplateInitHandler.java | 64 + .../hyts/apidoc/utility/ParserFactory.java | 146 + .../com/hyts/apidoc/utility/PathUtils.java | 77 + .../com/hyts/apidoc/utility/PropUtils.java | 104 + .../com/hyts/apidoc/utility/StringUtils.java | 106 + .../META-INF/resources/apidoc/column.html | 193 + .../META-INF/resources/apidoc/css/admin.css | 78 + .../META-INF/resources/apidoc/css/pintuer.css | 1083 + .../META-INF/resources/apidoc/dataInfo.html | 84 + .../META-INF/resources/apidoc/dataList.html | 90 + .../META-INF/resources/apidoc/images/bg.jpg | Bin 0 -> 103501 bytes .../resources/apidoc/images/tmbg-white.png | Bin 0 -> 1012 bytes .../META-INF/resources/apidoc/images/y.jpg | Bin 0 -> 16763 bytes .../src/main/resources/apache2.0.license | 17 + .../src/main/resources/apidoc.properties | 1 + coffice-toolbox-apidoc/src/test/java/TODO | 0 .../java/com/hyts/apidoc/test/TestParser.java | 39 + .../com/hyts/apidoc/test/TestScanner.java | 40 + .../src/test/resources/TODO | 0 coffice-toolbox-aspect/pom.xml | 119 + .../src/main/java/com/hyts/aop/AopProxy.java | 124 + .../com/hyts/aop/base/BaseAopHandler.java | 78 + .../java/com/hyts/aop/base/package-info.java | 21 + .../java/com/hyts/aop/error/AopException.java | 69 + .../aop/handler/cglib/CglibAopHandler.java | 82 + .../cglib/MethodInterceptorHandler.java | 98 + .../handler/common/AfterMethodHandler.java | 71 + .../handler/common/BeforeMethodHandler.java | 79 + .../handler/common/PointcutMethodHandler.java | 76 + .../handler/common/RoundMethodHandler.java | 80 + .../aop/handler/java/DefaultAopHandler.java | 113 + .../hyts/aop/handler/java/JdkAopHandler.java | 78 + .../hyts/aop/plugins/ThirdPartyPlugins.java | 29 + .../java/com/hyts/aop/pointcut/ScanAop.java | 42 + .../com/hyts/aop/pointcut/ScanPointcut.java | 52 + .../src/main/resources/TODO | 0 coffice-toolbox-aspect/src/test/java/TODO | 0 .../src/test/java/com/hyts/aop/test/DI.java | 47 + .../test/java/com/hyts/aop/test/TestDemo.java | 46 + .../java/com/hyts/aop/test/WeaveDemo.java | 46 + .../hyts/aop/test/cglib/AopSuperClass.java | 33 + .../com/hyts/aop/test/jdk/AopInterface.java | 35 + .../hyts/aop/test/jdk/AopInterfaceImpl.java | 40 + .../src/test/resources/TODO | 0 coffice-toolbox-binder/pom.xml | 76 + .../java/com/hyts/bind/base/BaseBinder.java | 84 + .../com/hyts/bind/base/BaseGuiceHandler.java | 45 + .../java/com/hyts/bind/base/BaseInjector.java | 135 + .../com/hyts/bind/binder/BinderService.java | 32 + .../hyts/bind/binder/DefaultClassBinder.java | 65 + .../com/hyts/bind/domain/BindDomains.java | 165 + .../hyts/bind/error/GuiceBindException.java | 53 + .../com/hyts/bind/facade/BindContext.java | 123 + .../hyts/bind/handler/DefaultBindHandler.java | 89 + .../bind/injector/DefaultClassInjector.java | 117 + .../com/hyts/bind/scanner/ScannerAdapter.java | 76 + .../src/main/resources/TODO | 0 .../java/com/hyts/bind/test/TestBind.java | 77 + .../java/com/hyts/bind/test/TestService.java | 32 + .../hyts/bind/test/TestServiceController.java | 36 + .../com/hyts/bind/test/TestServiceImpl.java | 40 + .../com/hyts/bind/test/TestServiceImpl2.java | 37 + .../src/test/resources/TODO | 0 coffice-toolbox-codegen/pom.xml | 107 + .../hyts/codegen/base/AbstractFileWriter.java | 46 + .../hyts/codegen/base/AnnotationModel.java | 96 + .../com/hyts/codegen/base/BuildModel.java | 67 + .../java/com/hyts/codegen/base/Generator.java | 18 + .../com/hyts/codegen/base/JavaDocModel.java | 96 + .../com/hyts/codegen/base/JavaFieldModel.java | 154 + .../hyts/codegen/base/JavaMethodModel.java | 206 + .../java/com/hyts/codegen/base/JavaModel.java | 209 + .../com/hyts/codegen/base/JavaTypeModel.java | 131 + .../hyts/codegen/jfinal/JfinalGenerator.java | 175 + .../jfinal/base/BaseJfinalCreator.java | 67 + .../codegen/jfinal/base/BaseJfinalWriter.java | 67 + .../jfinal/base/JFinalWriterConfig.java | 41 + .../codegen/jfinal/base/JavaCodeWriter.java | 120 + .../codegen/jfinal/base/JfinalCodeWriter.java | 105 + .../jfinal/build/JfinalExcBuilder.java | 112 + .../jfinal/config/JFinalWriterConfig.java | 41 + .../jfinal/config/JavaWriterConfig.java | 41 + .../jfinal/config/JfinalParamConfig.java | 37 + .../creator/DefaultJfinalCodeCreator.java | 195 + .../creator/DefaultJfinalCodesCreator.java | 95 + .../jfinal/model/JfinalBuildModel.java | 488 + .../jfinal/model/SimpleBuildModel.java | 299 + .../jfinal/writer/BaseJfinalWriter.java | 67 + .../jfinal/writer/JFinalWriterConfig.java | 41 + .../codegen/jfinal/writer/JavaCodeWriter.java | 120 + .../jfinal/writer/JfinalCodeWriter.java | 119 + .../codegen/mybatis/MybatisGenerator.java | 61 + .../mybatis/comment/CodeCommentGenerator.java | 300 + .../mybatis/writer/MybatisCodeWriter.java | 63 + .../codegen/mybatis/writer/MybatisWriter.java | 29 + .../src/main/java/org/.svn/entries | 31 + .../generator/api/CommentGenerator.java | 122 + .../api/DAOMethodNameCalculator.java | 153 + .../generator/api/FullyQualifiedTable.java | 336 + .../generator/api/IntrospectedColumn.java | 304 + .../mybatis/generator/api/JavaFormatter.java | 36 + .../generator/api/JavaTypeResolver.java | 87 + .../mybatis/generator/api/PluginAdapter.java | 454 + .../generator/api/ProgressCallback.java | 100 + .../mybatis/generator/api/ShellRunner.java | 228 + .../api/VerboseProgressCallback.java | 38 + .../mybatis/generator/api/XmlFormatter.java | 36 + .../api/dom/DefaultJavaFormatter.java | 39 + .../api/dom/DefaultXmlFormatter.java | 39 + .../generator/api/dom/OutputUtilities.java | 106 + .../api/dom/java/CompilationUnit.java | 63 + .../mybatis/generator/api/dom/java/Field.java | 151 + .../api/dom/java/FullyQualifiedJavaType.java | 484 + .../api/dom/java/InitializationBlock.java | 133 + .../generator/api/dom/java/InnerClass.java | 282 + .../generator/api/dom/java/InnerEnum.java | 239 + .../generator/api/dom/java/Interface.java | 228 + .../generator/api/dom/java/JavaElement.java | 129 + .../api/dom/java/JavaVisibility.java | 38 + .../generator/api/dom/java/Method.java | 305 + .../generator/api/dom/java/Parameter.java | 101 + .../api/dom/java/PrimitiveTypeWrapper.java | 125 + .../generator/api/dom/java/TopLevelClass.java | 145 + .../api/dom/java/TopLevelEnumeration.java | 140 + .../generator/api/dom/xml/Attribute.java | 57 + .../generator/api/dom/xml/Document.java | 93 + .../generator/api/dom/xml/Element.java | 31 + .../generator/api/dom/xml/TextElement.java | 45 + .../generator/api/dom/xml/XmlElement.java | 126 + .../org/mybatis/generator/api/package.html | 10 + .../generator/codegen/AbstractGenerator.java | 70 + .../codegen/AbstractJavaClientGenerator.java | 51 + .../codegen/AbstractJavaGenerator.java | 156 + .../codegen/AbstractXmlGenerator.java | 27 + .../generator/codegen/RootClassInfo.java | 126 + .../generator/codegen/XmlConstants.java | 53 + .../ibatis2/Ibatis2FormattingUtilities.java | 201 + .../IntrospectedTableIbatis2Java5Impl.java | 29 + .../IntrospectedTableMyBatis3SimpleImpl.java | 88 + .../mybatis3/MyBatis3FormattingUtilities.java | 184 + .../generator/config/ColumnOverride.java | 138 + .../generator/config/ColumnRenamingRule.java | 94 + .../config/CommentGeneratorConfiguration.java | 44 + .../generator/config/Configuration.java | 133 + .../generator/config/GeneratedKey.java | 144 + .../generator/config/IgnoredColumn.java | 92 + .../config/JDBCConnectionConfiguration.java | 103 + .../config/JavaTypeResolverConfiguration.java | 43 + .../generator/config/MergeConstants.java | 40 + .../mybatis/generator/config/ModelType.java | 56 + .../generator/config/PluginConfiguration.java | 52 + .../generator/config/PropertyHolder.java | 62 + .../generator/config/PropertyRegistry.java | 68 + .../generator/config/TableConfiguration.java | 544 + .../generator/config/TypedPropertyHolder.java | 48 + .../config/xml/ConfigurationParser.java | 163 + .../config/xml/ParserEntityResolver.java | 65 + .../config/xml/ParserErrorHandler.java | 75 + .../config/xml/ibator-config_1_0.dtd | 215 + .../xml/mybatis-generator-config_1_0.dtd | 214 + .../InvalidConfigurationException.java | 48 + .../generator/exception/ShellException.java | 55 + .../exception/XMLParserException.java | 56 + .../internal/DefaultCommentGenerator.java | 344 + .../DefaultDAOMethodNameCalculator.java | 172 + .../mybatis/generator/internal/DomWriter.java | 341 + .../ExtendedDAOMethodNameCalculator.java | 261 + .../internal/NullProgressCallback.java | 52 + .../generator/internal/PluginAggregator.java | 1195 + .../generator/internal/XmlFileMergerJaxp.java | 246 + .../internal/db/ActualTableName.java | 73 + .../internal/db/ConnectionFactory.java | 90 + .../internal/db/DatabaseDialects.java | 79 + .../internal/db/DatabaseIntrospector.java | 623 + .../internal/db/SqlReservedWords.java | 978 + .../internal/rules/ConditionalModelRules.java | 76 + .../internal/rules/FlatModelRules.java | 63 + .../rules/HierarchicalModelRules.java | 68 + .../generator/internal/rules/Rules.java | 250 + .../internal/rules/RulesDelegate.java | 175 + .../types/JavaTypeResolverDefaultImpl.java | 215 + .../generator/internal/types/Jdbc4Types.java | 10 + .../types/JdbcTypeNameTranslator.java | 146 + .../internal/util/ClassloaderUtility.java | 71 + .../generator/internal/util/EqualsUtil.java | 65 + .../generator/internal/util/HashCodeUtil.java | 114 + .../internal/util/JavaBeansUtil.java | 166 + .../internal/util/StringUtility.java | 105 + .../internal/util/messages/Messages.java | 69 + .../util/messages/messages.properties | 128 + .../generator/logging/AbstractLogFactory.java | 27 + .../generator/logging/JdkLoggingImpl.java | 68 + .../org/mybatis/generator/logging/Log.java | 33 + .../mybatis/generator/logging/Log4jImpl.java | 52 + .../mybatis/generator/logging/LogFactory.java | 77 + .../plugins/CaseInsensitiveLikePlugin.java | 109 + .../plugins/EqualsHashCodePlugin.java | 311 + .../plugins/RenameExampleClassPlugin.java | 100 + .../generator/plugins/SerializablePlugin.java | 110 + .../generator/plugins/ToStringPlugin.java | 86 + .../plugins/VirtualPrimaryKeyPlugin.java | 57 + .../src/main/resources/generatorConfig.xml | 51 + .../mybatis-generator-core-1.3.2-sources.jar | Bin 0 -> 411564 bytes .../src/main/resources/readMe.txt | 25 + coffice-toolbox-codegen/src/test/java/TODO | 0 .../src/test/java/TestJfinalGenerator.java | 74 + .../src/test/resources/TODO | 0 coffice-toolbox-crawler4j/pom.xml | 11 + coffice-toolbox-dbmeta/pom.xml | 19 + .../java/com/hyts/dbmeta/base/Dialect.java | 29 + .../dbmeta/config/Db2ConnectionConfig.java | 13 + .../dbmeta/config/MysqlConnectionConfig.java | 135 + .../dbmeta/driver/DbDriverClassConfig.java | 39 + .../exception/DataBaseMetaException.java | 24 + .../dbmeta/handler/DBConnectionHandler.java | 60 + .../dbmeta/handler/DBMetadataHandler.java | 87 + .../handler/mysql/MySqlConnectionHandler.java | 58 + .../com/hyts/dbmeta/model/ColumnMetadata.java | 13 + .../hyts/dbmeta/model/DataSourceMetadata.java | 83 + .../hyts/dbmeta/model/ProcedureMetadata.java | 13 + .../hyts/dbmeta/model/ResultSetMetadata.java | 13 + .../com/hyts/dbmeta/model/TableMetadata.java | 50 + .../hyts/dbmeta/model/TriggerMetadata.java | 13 + .../com/hyts/dbmeta/model/ViewMetadata.java | 13 + .../java/com/hyts/datameta/TestDBMeta.java | 30 + coffice-toolbox-guava/pom.xml | 31 + .../java/com/hyts/guava/String/Strings.java | 521 + .../java/com/hyts/guava/array/Arrays.java | 60 + .../src/main/java/com/hyts/guava/bio/BIO.java | 223 + .../com/hyts/guava/cache/CacheHandler.java | 34 + .../java/com/hyts/guava/charset/Charsets.java | 29 + .../com/hyts/guava/config/CharsetConfig.java | 73 + .../com/hyts/guava/config/StringConfig.java | 51 + .../com/hyts/guava/config/ValidateConfig.java | 66 + .../com/hyts/guava/exception/Exceptions.java | 150 + .../main/java/com/hyts/guava/hash/Hashs.java | 428 + .../imcollection/ImmutableCollections.java | 45 + .../guava/imcollection/ImmutableLists.java | 95 + .../guava/imcollection/ImmutableMaps.java | 29 + .../guava/imcollection/ImmutableSets.java | 92 + .../imcollection/ImmutableSortedSets.java | 92 + .../com/hyts/guava/imcollection/Tables.java | 29 + .../main/java/com/hyts/guava/math/Maths.java | 78 + .../java/com/hyts/guava/object/Objects.java | 211 + .../com/hyts/guava/validator/Validates.java | 378 + ...1\346\225\231\347\250\213\343\200\221.pdf" | 29439 ++++++++++++++++ .../test/java/com/hyts/guava/TestModel.java | 63 + .../test/java/com/hyts/guava/TestObject.java | 43 + .../test/java/com/hyts/guava/TestString.java | 29 + coffice-toolbox-jlogger/pom.xml | 38 + .../com/hyts/logger/base/Log4jLogger.java | 49 + .../java/com/hyts/logger/config/Config.java | 44 + .../com/hyts/logger/error/MyLogException.java | 53 + .../hyts/logger/factory/LoggerFactory.java | 107 + .../hyts/logger/manager/LoggerHandler.java | 195 + .../hyts/logger/manager/LoggerManager.java | 77 + .../com/hyts/logger/util/ReadJarUtil.java | 49 + .../com/hyts/logger/util/StringUtils.java | 98 + .../src/main/resources/logging.properties | 59 + .../com/hyts/logger/example/LoggerTest.java | 41 + coffice-toolbox-joda/pom.xml | 10 + coffice-toolbox-jpdf/pom.xml | 75 + .../java/com/hyts/jpdf/config/PdfConfig.java | 38 + .../com/hyts/jpdf/element/PdfMetaElement.java | 29 + .../hyts/jpdf/element/PdfOperaElement.java | 65 + .../hyts/jpdf/handler/AbstractPdfHandler.java | 59 + .../hyts/jpdf/handler/DefaultPdfHandler.java | 141 + .../com/hyts/jpdf/utility/FreemarkerUtil.java | 80 + .../java/com/hyts/jpdf/utility/PathUtil.java | 56 + .../src/main/resources/logo.png | Bin 0 -> 93553 bytes .../src/main/resources/simhei.ttf | Bin 0 -> 10044356 bytes .../src/test/java/TestMthod.java | 51 + coffice-toolbox-restlet/pom.xml | 123 + .../restlet/application/RestApplication.java | 61 + .../restlet/base/DispatcherApplication.java | 71 + .../com/hyts/restlet/config/ServerConfig.java | 44 + .../hyts/restlet/manager/ServerManager.java | 54 + .../com/hyts/restlet/model/RestModel.java | 31 + .../com/hyts/restlet/model/ServerModel.java | 173 + .../restlet/resource/ManagerResource.java | 29 + .../restlet/resource/MonitorResource.java | 48 + .../hyts/restlet/resource/SystemResource.java | 51 + .../hyts/restlet/server/BootstrapServer.java | 109 + .../src/main/resources/logging.properties | 59 + coffice-toolbox-scanner/pom.xml | 115 + .../hyts/scanner/base/AbstractScanner.java | 42 + .../com/hyts/scanner/base/BaseApiParser.java | 33 + .../com/hyts/scanner/bean/ScanBaseObject.java | 58 + .../com/hyts/scanner/bean/ScanExtObject.java | 76 + .../hyts/scanner/bean/ScanResultObject.java | 104 + .../com/hyts/scanner/config/ScanRule.java | 35 + .../hyts/scanner/config/ScanRuleConfig.java | 60 + .../com/hyts/scanner/core/JarScanner.java | 66 + .../java/com/hyts/scanner/core/Scanner.java | 109 + .../scanner/core/SourceAndJarHandler.java | 102 + .../com/hyts/scanner/filter/ClassFilter.java | 44 + .../hyts/scanner/filter/ClassNameFilter.java | 73 + .../hyts/scanner/helper/AnnotationHelper.java | 85 + .../com/hyts/scanner/helper/ClassHelper.java | 144 + .../com/hyts/scanner/helper/JarHelper.java | 225 + .../com/hyts/scanner/helper/ScanHelper.java | 144 + .../com/hyts/scanner/utility/PathUtils.java | 99 + .../com/hyts/scanner/utility/StringUtils.java | 106 + .../src/main/resources/TODO | 0 coffice-toolbox-scanner/src/test/java/TODO | 0 .../src/test/java/TestScanner.java | 27 + .../src/test/resources/TODO | 0 .../jcrontab.log | 14 + .../coffice-toolbox-schedule-Jcrontab/pom.xml | 25 + .../hyts/jcrontab/boot/JCrontabBootStrap.java | 92 + .../java/com/hyts/jcrontab/package-info.java | 25 + .../src/main/resources/Jcrontab-2.0-RC0.jar | Bin 0 -> 138877 bytes .../src/main/resources/jcrontab.properties | 44 + .../src/main/resources/log4j.properties | 9 + .../coffice-toolbox-schedule-quartz/pom.xml | 40 + .../quartz/base/AbstractJobManager.java | 58 + .../quartz/base/AbstractSchedulerManager.java | 81 + .../quartz/base/AbstractTriggerManager.java | 40 + .../quartz/base/BaseSchedulerManager.java | 162 + .../quartz/config/DefaultJobConfig.java | 71 + .../quartz/daemon/MonitorSchedule.java | 70 + .../schedule/quartz/error/ScheduleError.java | 72 + .../executor/DefaultScheduleExecutor.java | 289 + .../hyts/schedule/quartz/handler/Task.java | 125 + .../quartz/manager/DefaultJobManager.java | 98 + .../quartz/manager/DefaultTriggerManager.java | 111 + .../quartz/model/CronTriggerBean.java | 29 + .../hyts/schedule/quartz/model/JobBean.java | 222 + .../quartz/model/SimpleTriggerBean.java | 216 + .../schedule/quartz/model/TriggerBean.java | 144 + .../src/main/resources/log4j.properties | 14 + .../src/test/java/DefaultJob.java | 55 + .../src/test/java/TestExecutor.java | 66 + .../pom.xml | 60 + .../wjcrontab/bootstrap/JcrontabInitizer.java | 34 + .../src/main/resources/Jcrontab-2.0-RC0.jar | Bin 0 -> 138877 bytes .../src/main/resources/jcrontab.properties | 44 + .../src/main/resources/log4j.properties | 9 + coffice-toolbox-schedule/pom.xml | 16 + coffice-toolbox-server/pom.xml | 61 + .../alex/jetty/bean/JettyRunConfigure.java | 106 + .../net/alex/jetty/demo/StartJettyServer.java | 64 + .../alex/jetty/error/JettyServerError.java | 50 + .../net/alex/jetty/server/JettyServer.java | 220 + .../resources/jetty/conf/logging.properties | 59 + .../src/main/resources/jetty/context/test.xml | 97 + .../main/resources/jetty/etc/jetty-start.xml | 60 + .../src/main/resources/jetty/etc/jetty.xml | 60 + .../main/resources/jetty/etc/jetty.xml.bak | 61 + .../main/resources/jetty/etc/webdefault.xml | 410 + .../main/resources/jetty/lib/ext/.donotdelete | 0 .../resources/jetty/lib/policy/global.policy | 43 + .../jetty/lib/policy/jetty-jmx.policy | 54 + .../jetty/lib/policy/jetty-start.policy | 40 + .../jetty/lib/policy/jetty-work.policy | 19 + .../resources/jetty/lib/policy/jetty.policy | 96 + .../jetty/lib/policy/temp-dirs.policy | 30 + coffice-toolbox-shell/pom.xml | 129 + .../src/main/java/com/hyts/shell/SSH.java | 108 + .../com/hyts/shell/cache/CacheMonitor.java | 48 + .../shell/cache/ConnectionCacheManager.java | 92 + .../java/com/hyts/shell/cache/ICache.java | 78 + .../com/hyts/shell/cache/ICacheFactory.java | 43 + .../hyts/shell/cache/SessionCacheManager.java | 93 + .../java/com/hyts/shell/config/SSHConfig.java | 42 + .../com/hyts/shell/error/SSHException.java | 69 + .../com/hyts/shell/executor/EthzExecutor.java | 229 + .../hyts/shell/executor/JcraftExecutor.java | 236 + .../hyts/shell/executor/base/Executor.java | 60 + .../shell/handler/AbstractStreamHandler.java | 41 + .../hyts/shell/handler/BaseProcessStream.java | 60 + .../com/hyts/shell/model/ExecuteDomain.java | 44 + .../com/hyts/shell/model/ResultDomain.java | 138 + .../hyts/shell/model/StringResultDomain.java | 29 + .../java/com/hyts/shell/model/UserRealm.java | 189 + .../test/java/com/hyts/test/ShellTest.java | 45 + coffice-toolbox-template/pom.xml | 32 + .../template/common/AbstractFileWriter.java | 46 + .../template/common/BaseJavaFileTemplate.java | 132 + .../template/common/BasePropFileTemplate.java | 35 + .../template/common/BaseXmlFileTemplate.java | 29 + .../template/common/BaseYamlFileTemplate.java | 29 + .../template/config/FileAttributeConfig.java | 33 + .../template/config/JavaTemplateConfig.java | 167 + .../freemarker/FreemarkerContext.java | 159 + .../template/freemarker/FreemarkerStream.java | 162 + .../freemarker/FreemarkerTemplate.java | 68 + .../template/strformat/JavaCodeConfig.java | 42 + .../template/strformat/JavaCodeExecutor.java | 120 + .../template/strformat/JavaCodeTemplate.java | 303 + .../resources/META-INF/resources/code.ftl | 9 + .../src/main/resources/templates/code.ftl | 9 + pom.xml | 159 + 427 files changed, 71880 insertions(+) create mode 100644 coffice-toolbox-apidoc/pom.xml create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisEngine.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisTemplate.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AbstractScanner.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AnnotationDocConfig.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/BaseApiParser.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanBaseObject.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanExtObject.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanResultObject.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/AnalysisConfig.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ParseDocType.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRule.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRuleConfig.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/error/ApiDocError.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocHandler.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocSupport.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDefination.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDoc.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiParam.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/AnnotationApiParser.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/JavaDocApiParser.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/SwaggerApiParser.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/JarScanner.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/Scanner.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/SourceScanner.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassFilter.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassNameFilter.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/AnnotationHelper.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ClassHelper.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ScanHelper.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/servlet/ApiDocServlet.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocConfiguration.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocServletConfiguration.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateDataHandler.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateInitHandler.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/ParserFactory.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PathUtils.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PropUtils.java create mode 100644 coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/StringUtils.java create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/column.html create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/admin.css create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/pintuer.css create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataInfo.html create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataList.html create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/bg.jpg create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/tmbg-white.png create mode 100644 coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/y.jpg create mode 100644 coffice-toolbox-apidoc/src/main/resources/apache2.0.license create mode 100644 coffice-toolbox-apidoc/src/main/resources/apidoc.properties create mode 100644 coffice-toolbox-apidoc/src/test/java/TODO create mode 100644 coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestParser.java create mode 100644 coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestScanner.java create mode 100644 coffice-toolbox-apidoc/src/test/resources/TODO create mode 100644 coffice-toolbox-aspect/pom.xml create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/AopProxy.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/BaseAopHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/package-info.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/error/AopException.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/CglibAopHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/MethodInterceptorHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/AfterMethodHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/BeforeMethodHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/PointcutMethodHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/RoundMethodHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/java/DefaultAopHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/java/JdkAopHandler.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/plugins/ThirdPartyPlugins.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanAop.java create mode 100644 coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanPointcut.java create mode 100644 coffice-toolbox-aspect/src/main/resources/TODO create mode 100644 coffice-toolbox-aspect/src/test/java/TODO create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/DI.java create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/TestDemo.java create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/WeaveDemo.java create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/cglib/AopSuperClass.java create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterface.java create mode 100644 coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterfaceImpl.java create mode 100644 coffice-toolbox-aspect/src/test/resources/TODO create mode 100644 coffice-toolbox-binder/pom.xml create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseBinder.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseGuiceHandler.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseInjector.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/BinderService.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/DefaultClassBinder.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/domain/BindDomains.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/error/GuiceBindException.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/facade/BindContext.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/handler/DefaultBindHandler.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/injector/DefaultClassInjector.java create mode 100644 coffice-toolbox-binder/src/main/java/com/hyts/bind/scanner/ScannerAdapter.java create mode 100644 coffice-toolbox-binder/src/main/resources/TODO create mode 100644 coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestBind.java create mode 100644 coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestService.java create mode 100644 coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceController.java create mode 100644 coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl.java create mode 100644 coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl2.java create mode 100644 coffice-toolbox-binder/src/test/resources/TODO create mode 100644 coffice-toolbox-codegen/pom.xml create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AbstractFileWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AnnotationModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/BuildModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/Generator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaDocModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaFieldModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaMethodModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaTypeModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/JfinalGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalCreator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JFinalWriterConfig.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JavaCodeWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JfinalCodeWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/build/JfinalExcBuilder.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JFinalWriterConfig.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JavaWriterConfig.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JfinalParamConfig.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodeCreator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodesCreator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/JfinalBuildModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/SimpleBuildModel.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/BaseJfinalWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JFinalWriterConfig.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JavaCodeWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JfinalCodeWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/MybatisGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/comment/CodeCommentGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisCodeWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/.svn/entries create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/CommentGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/DAOMethodNameCalculator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/FullyQualifiedTable.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/IntrospectedColumn.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaFormatter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaTypeResolver.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/PluginAdapter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ProgressCallback.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ShellRunner.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/VerboseProgressCallback.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/XmlFormatter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultJavaFormatter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultXmlFormatter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/OutputUtilities.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/CompilationUnit.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Field.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/FullyQualifiedJavaType.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InitializationBlock.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerClass.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerEnum.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Interface.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaElement.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaVisibility.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Method.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Parameter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/PrimitiveTypeWrapper.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelClass.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelEnumeration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Attribute.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Document.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Element.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/TextElement.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/XmlElement.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/package.html create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaClientGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractXmlGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/RootClassInfo.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/XmlConstants.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/Ibatis2FormattingUtilities.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/IntrospectedTableIbatis2Java5Impl.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/IntrospectedTableMyBatis3SimpleImpl.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/MyBatis3FormattingUtilities.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnOverride.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnRenamingRule.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/CommentGeneratorConfiguration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/Configuration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/GeneratedKey.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/IgnoredColumn.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JDBCConnectionConfiguration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JavaTypeResolverConfiguration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/MergeConstants.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ModelType.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PluginConfiguration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyHolder.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyRegistry.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TableConfiguration.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TypedPropertyHolder.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ConfigurationParser.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserEntityResolver.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserErrorHandler.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ibator-config_1_0.dtd create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/InvalidConfigurationException.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/ShellException.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/XMLParserException.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultDAOMethodNameCalculator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DomWriter.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/ExtendedDAOMethodNameCalculator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/NullProgressCallback.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/PluginAggregator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/XmlFileMergerJaxp.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ActualTableName.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ConnectionFactory.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseDialects.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseIntrospector.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/SqlReservedWords.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/ConditionalModelRules.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/FlatModelRules.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/HierarchicalModelRules.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/Rules.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/RulesDelegate.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JavaTypeResolverDefaultImpl.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/Jdbc4Types.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JdbcTypeNameTranslator.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/ClassloaderUtility.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/EqualsUtil.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/HashCodeUtil.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/JavaBeansUtil.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/StringUtility.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/Messages.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/messages.properties create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/AbstractLogFactory.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/JdkLoggingImpl.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log4jImpl.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/LogFactory.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/CaseInsensitiveLikePlugin.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/EqualsHashCodePlugin.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/RenameExampleClassPlugin.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/SerializablePlugin.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/ToStringPlugin.java create mode 100644 coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/VirtualPrimaryKeyPlugin.java create mode 100644 coffice-toolbox-codegen/src/main/resources/generatorConfig.xml create mode 100644 coffice-toolbox-codegen/src/main/resources/mybatis-generator-core-1.3.2-sources.jar create mode 100644 coffice-toolbox-codegen/src/main/resources/readMe.txt create mode 100644 coffice-toolbox-codegen/src/test/java/TODO create mode 100644 coffice-toolbox-codegen/src/test/java/TestJfinalGenerator.java create mode 100644 coffice-toolbox-codegen/src/test/resources/TODO create mode 100644 coffice-toolbox-crawler4j/pom.xml create mode 100644 coffice-toolbox-dbmeta/pom.xml create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/base/Dialect.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/config/Db2ConnectionConfig.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/config/MysqlConnectionConfig.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/driver/DbDriverClassConfig.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/exception/DataBaseMetaException.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/handler/DBConnectionHandler.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/handler/DBMetadataHandler.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/handler/mysql/MySqlConnectionHandler.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/ColumnMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/DataSourceMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/ProcedureMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/ResultSetMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/TableMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/TriggerMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/main/java/com/hyts/dbmeta/model/ViewMetadata.java create mode 100644 coffice-toolbox-dbmeta/src/test/java/com/hyts/datameta/TestDBMeta.java create mode 100644 coffice-toolbox-guava/pom.xml create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/String/Strings.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/array/Arrays.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/bio/BIO.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/cache/CacheHandler.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/charset/Charsets.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/config/CharsetConfig.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/config/StringConfig.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/config/ValidateConfig.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/exception/Exceptions.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/hash/Hashs.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/ImmutableCollections.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/ImmutableLists.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/ImmutableMaps.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/ImmutableSets.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/ImmutableSortedSets.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/imcollection/Tables.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/math/Maths.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/object/Objects.java create mode 100644 coffice-toolbox-guava/src/main/java/com/hyts/guava/validator/Validates.java create mode 100644 "coffice-toolbox-guava/src/main/resources/\343\200\220Guava\345\256\230\346\226\271\346\225\231\347\250\213\343\200\221.pdf" create mode 100644 coffice-toolbox-guava/src/test/java/com/hyts/guava/TestModel.java create mode 100644 coffice-toolbox-guava/src/test/java/com/hyts/guava/TestObject.java create mode 100644 coffice-toolbox-guava/src/test/java/com/hyts/guava/TestString.java create mode 100644 coffice-toolbox-jlogger/pom.xml create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/base/Log4jLogger.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/config/Config.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/error/MyLogException.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/factory/LoggerFactory.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/manager/LoggerHandler.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/manager/LoggerManager.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/util/ReadJarUtil.java create mode 100644 coffice-toolbox-jlogger/src/main/java/com/hyts/logger/util/StringUtils.java create mode 100644 coffice-toolbox-jlogger/src/main/resources/logging.properties create mode 100644 coffice-toolbox-jlogger/src/test/java/com/hyts/logger/example/LoggerTest.java create mode 100644 coffice-toolbox-joda/pom.xml create mode 100644 coffice-toolbox-jpdf/pom.xml create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/config/PdfConfig.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/element/PdfMetaElement.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/element/PdfOperaElement.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/handler/AbstractPdfHandler.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/handler/DefaultPdfHandler.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/utility/FreemarkerUtil.java create mode 100644 coffice-toolbox-jpdf/src/main/java/com/hyts/jpdf/utility/PathUtil.java create mode 100644 coffice-toolbox-jpdf/src/main/resources/logo.png create mode 100644 coffice-toolbox-jpdf/src/main/resources/simhei.ttf create mode 100644 coffice-toolbox-jpdf/src/test/java/TestMthod.java create mode 100644 coffice-toolbox-restlet/pom.xml create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/application/RestApplication.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/base/DispatcherApplication.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/config/ServerConfig.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/manager/ServerManager.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/model/RestModel.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/model/ServerModel.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/resource/ManagerResource.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/resource/MonitorResource.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/resource/SystemResource.java create mode 100644 coffice-toolbox-restlet/src/main/java/com/hyts/restlet/server/BootstrapServer.java create mode 100644 coffice-toolbox-restlet/src/main/resources/logging.properties create mode 100644 coffice-toolbox-scanner/pom.xml create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/base/AbstractScanner.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/base/BaseApiParser.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/bean/ScanBaseObject.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/bean/ScanExtObject.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/bean/ScanResultObject.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/config/ScanRule.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/config/ScanRuleConfig.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/core/JarScanner.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/core/Scanner.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/core/SourceAndJarHandler.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/filter/ClassFilter.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/filter/ClassNameFilter.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/helper/AnnotationHelper.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/helper/ClassHelper.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/helper/JarHelper.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/helper/ScanHelper.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/utility/PathUtils.java create mode 100644 coffice-toolbox-scanner/src/main/java/com/hyts/scanner/utility/StringUtils.java create mode 100644 coffice-toolbox-scanner/src/main/resources/TODO create mode 100644 coffice-toolbox-scanner/src/test/java/TODO create mode 100644 coffice-toolbox-scanner/src/test/java/TestScanner.java create mode 100644 coffice-toolbox-scanner/src/test/resources/TODO create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/jcrontab.log create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/pom.xml create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/src/main/java/com/hyts/jcrontab/boot/JCrontabBootStrap.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/src/main/java/com/hyts/jcrontab/package-info.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/src/main/resources/Jcrontab-2.0-RC0.jar create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/src/main/resources/jcrontab.properties create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-Jcrontab/src/main/resources/log4j.properties create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/pom.xml create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/base/AbstractJobManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/base/AbstractSchedulerManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/base/AbstractTriggerManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/base/BaseSchedulerManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/config/DefaultJobConfig.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/daemon/MonitorSchedule.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/error/ScheduleError.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/executor/DefaultScheduleExecutor.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/handler/Task.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/manager/DefaultJobManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/manager/DefaultTriggerManager.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/model/CronTriggerBean.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/model/JobBean.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/model/SimpleTriggerBean.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/java/com/hyts/schedule/quartz/model/TriggerBean.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/main/resources/log4j.properties create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/test/java/DefaultJob.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-quartz/src/test/java/TestExecutor.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-wjcrontab/pom.xml create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-wjcrontab/src/main/java/com/hyts/schduler/wjcrontab/bootstrap/JcrontabInitizer.java create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-wjcrontab/src/main/resources/Jcrontab-2.0-RC0.jar create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-wjcrontab/src/main/resources/jcrontab.properties create mode 100644 coffice-toolbox-schedule/coffice-toolbox-schedule-wjcrontab/src/main/resources/log4j.properties create mode 100644 coffice-toolbox-schedule/pom.xml create mode 100644 coffice-toolbox-server/pom.xml create mode 100644 coffice-toolbox-server/src/main/java/net/alex/jetty/bean/JettyRunConfigure.java create mode 100644 coffice-toolbox-server/src/main/java/net/alex/jetty/demo/StartJettyServer.java create mode 100644 coffice-toolbox-server/src/main/java/net/alex/jetty/error/JettyServerError.java create mode 100644 coffice-toolbox-server/src/main/java/net/alex/jetty/server/JettyServer.java create mode 100644 coffice-toolbox-server/src/main/resources/jetty/conf/logging.properties create mode 100644 coffice-toolbox-server/src/main/resources/jetty/context/test.xml create mode 100644 coffice-toolbox-server/src/main/resources/jetty/etc/jetty-start.xml create mode 100644 coffice-toolbox-server/src/main/resources/jetty/etc/jetty.xml create mode 100644 coffice-toolbox-server/src/main/resources/jetty/etc/jetty.xml.bak create mode 100644 coffice-toolbox-server/src/main/resources/jetty/etc/webdefault.xml create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/ext/.donotdelete create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/global.policy create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/jetty-jmx.policy create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/jetty-start.policy create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/jetty-work.policy create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/jetty.policy create mode 100644 coffice-toolbox-server/src/main/resources/jetty/lib/policy/temp-dirs.policy create mode 100644 coffice-toolbox-shell/pom.xml create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/SSH.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/cache/CacheMonitor.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/cache/ConnectionCacheManager.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/cache/ICache.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/cache/ICacheFactory.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/cache/SessionCacheManager.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/config/SSHConfig.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/error/SSHException.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/executor/EthzExecutor.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/executor/JcraftExecutor.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/executor/base/Executor.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/handler/AbstractStreamHandler.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/handler/BaseProcessStream.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/model/ExecuteDomain.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/model/ResultDomain.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/model/StringResultDomain.java create mode 100644 coffice-toolbox-shell/src/main/java/com/hyts/shell/model/UserRealm.java create mode 100644 coffice-toolbox-shell/src/test/java/com/hyts/test/ShellTest.java create mode 100644 coffice-toolbox-template/pom.xml create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/common/AbstractFileWriter.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/common/BaseJavaFileTemplate.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/common/BasePropFileTemplate.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/common/BaseXmlFileTemplate.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/common/BaseYamlFileTemplate.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/config/FileAttributeConfig.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/config/JavaTemplateConfig.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/freemarker/FreemarkerContext.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/freemarker/FreemarkerStream.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/freemarker/FreemarkerTemplate.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/strformat/JavaCodeConfig.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/strformat/JavaCodeExecutor.java create mode 100644 coffice-toolbox-template/src/main/java/com/hyts/template/strformat/JavaCodeTemplate.java create mode 100644 coffice-toolbox-template/src/main/resources/META-INF/resources/code.ftl create mode 100644 coffice-toolbox-template/src/main/resources/templates/code.ftl create mode 100644 pom.xml diff --git a/coffice-toolbox-apidoc/pom.xml b/coffice-toolbox-apidoc/pom.xml new file mode 100644 index 0000000..b3c2ca9 --- /dev/null +++ b/coffice-toolbox-apidoc/pom.xml @@ -0,0 +1,77 @@ + + 4.0.0 + + com.hyts + coffice-toolbox + 1.0.0 + + coffice-toolbox-apidoc + + + com.sun + tools + 1.8 + + ${env.JAVA_HOME}/lib/tools.jar + system + + + + javax.servlet + servlet-api + 3.0-alpha-1 + provided + + + com.hyts + coffice-toolbox-template + 1.0.0 + + + org.springframework.boot + spring-boot-starter-web + 2.0.0.RELEASE + provided + + + + + + + + maven-assembly-plugin + + + make-assembly + + single + + + + + + jar-with-dependencies + + + + + + \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisEngine.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisEngine.java new file mode 100644 index 0000000..f2430e5 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisEngine.java @@ -0,0 +1,61 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.analysis; + +import com.hyts.apidoc.model.ApiDoc; +import com.sun.javadoc.Tag; + +/** + * @title AnalysisEngine.java + * @package com.hyts.apidoc.analysis + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class AnalysisEngine { + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param tags 标签集合 + * @return ApiDoc + * @exception + */ + public static ApiDoc analysisTypeHeader(Tag[] tags) { + return new AnalysisTemplate(new ApiDoc(),tags).injectTypeHeader().getApiDoc(); + } + + /** + * @author:Alex/Libo + * @create-date:2018/10/26 + * @create-time:21:53 + * @method-name: + * @param: + * @return: + * @description:a + */ + public static ApiDoc analysisMethodHeader(Tag[] tags,ApiDoc apiDoc) { + return new AnalysisTemplate(apiDoc,tags).injectMethodHeader().getApiDoc(); + } + + public void analysis(String analysisComment) { + + + + } +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisTemplate.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisTemplate.java new file mode 100644 index 0000000..e4aec39 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/analysis/AnalysisTemplate.java @@ -0,0 +1,171 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.analysis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.hyts.apidoc.config.AnalysisConfig; +import com.hyts.apidoc.model.ApiDefination; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.model.ApiParam; +import com.sun.javadoc.Tag; +import com.sun.tools.javac.code.Attribute.Array; + +/** + * @title AnalysisTemplate.java + * @package com.hyts.apidoc.analysis + * @description TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月24日 + * @version V1.0 + */ +public class AnalysisTemplate { + + /** + *

api文档Doc对象

+ * @fieldName apiDoc + * @fieldType ApiDoc + */ + private ApiDoc apiDoc; + + /** + *

{字段的描述}

+ * @fieldName tags + * @fieldType Tag[] + */ + private Tag[] tags; + + /** + * @constructor:AnalysisTemplate + * @param apiDoc + */ + public AnalysisTemplate(ApiDoc apiDoc,Tag[] tags) { + super(); + this.apiDoc = apiDoc; + this.tags = tags; + } + + /** + * @return + * @exception + */ + public AnalysisTemplate injectTypeHeader() { + //循环遍历数据信息 + for(AnalysisConfig config:AnalysisConfig.INSTANCE.getValues()) { + for(int i = 0 ; i < tags.length; i++){ + if(config.getCode().equalsIgnoreCase(tags[i].name())) { + switch(config) { + case EXT_TYPE_HEADER_TITLE_NAME: + apiDoc.setApiTypeName(tags[i].text()); + break; + case TYPE_HEADER_TITLE_DESC: + apiDoc.setApiDescription(tags[i].text().replaceAll("\n|\r|\t|\\s"," ")); + break; + case TYPE_HEADER_TITLE_AUTHOR: + apiDoc.setAuthor(tags[i].text()); + break; + case TYPE_HEADER_TITLE_DATE: + apiDoc.setDate(tags[i].text()); + break; + case TYPE_HEADER_TITLE_VERSION: + apiDoc.setVersion(tags[i].text()); + break; + case TYPE_HEADER_TITLE_PACKAGE: + apiDoc.setPackageName(tags[i].text()); + break; + default: + break; + } + } + } + } + return this; + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @exception + */ + public AnalysisTemplate injectMethodHeader() { + //循环遍历数据信息 + if(apiDoc.getApiDefinationList() == null || apiDoc.getApiDefinationList().isEmpty()){ + apiDoc.setApiDefinationList(new ArrayList()); + } + //创建局部异常列表 + List localExceptionList = new ArrayList<>(); + //创建参数列表 + List localInParamList = new ArrayList<>(); + List localoutParamList = new ArrayList<>(); + ApiDefination defination = new ApiDefination(); + for(int i = 0 ; i < tags.length; i++){ + for(AnalysisConfig config:AnalysisConfig.INSTANCE.getValues()) { + if(config.getCode().equalsIgnoreCase(tags[i].name())) { + switch(config) { + case METHOD_HEADER_EXCEPTION: + localExceptionList.add(tags[i].text()); + break; + case METHOD_HEADER_THROWS: + localExceptionList.add(tags[i].text()); + break; + case METHOD_HEADER_RETURN: + ApiParam inParam = new ApiParam(); + inParam.setIsRequired("是"); + inParam.setParamName(tags[i].text()); + inParam.setParamDescription(tags[i].text()); + localoutParamList.add(inParam); + break; + case METHOD_HEADER_PARAM: + ApiParam outParam = new ApiParam(); + outParam.setIsRequired("是"); + outParam.setParamName(tags[i].text()); + outParam.setParamDescription(tags[i].text()); + localInParamList.add(outParam); + break; + case METHOD_HEADER_NAME: + defination.setName(tags[i].text()); + break; + default: + break; + } + } + } + + } + defination.setPackageName(apiDoc.getPackageName()); + defination.setExceptionList(localExceptionList); + defination.setInputParameters(localInParamList); + defination.setOutputParameters(localoutParamList); + apiDoc.getApiDefinationList().add(defination); + return this; + } + + /** + * @name apiDoc's getter method + * @return apiDoc + */ + public ApiDoc getApiDoc() { + return apiDoc; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(AnalysisConfig.INSTANCE.getValues())); + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AbstractScanner.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AbstractScanner.java new file mode 100644 index 0000000..006adff --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AbstractScanner.java @@ -0,0 +1,44 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.base; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanExtObject; +import com.hyts.apidoc.bean.ScanResultObject; + +/** + * @title AbstractScanner.java + * @package com.hyts.apidoc.base + * @description 抽象力度的扫描器,用于扫描系统结构包中class类 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public abstract class AbstractScanner { + + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanObject + * @return + * @exception + */ + public abstract ScanResultObject scan(ScanBaseObject scanObject); + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AnnotationDocConfig.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AnnotationDocConfig.java new file mode 100644 index 0000000..d021190 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/AnnotationDocConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.base; + +import com.hyts.apidoc.config.AnalysisConfig; + +/** + * @author LiBo/Alex + * @version V1.0 + */ +public interface AnnotationDocConfig { + + AnalysisConfig[] getValues(); + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/BaseApiParser.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/BaseApiParser.java new file mode 100644 index 0000000..20c0e49 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/base/BaseApiParser.java @@ -0,0 +1,43 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.base; + +import java.util.List; + +/** + * @title BaseApiParser.java + * @package com.hyts.apidoc.base + * @description 操作抽象API解析器接口:用于处理对应的type类的解析器 + * 有很多子类实现进行构建解析的不同方案以及类型 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +@FunctionalInterface +public interface BaseApiParser { + + /** + * generateDoc + *

创建Javadoc文本操作

+ * @param param 参数类型:可以为javadoc解析出的api结果 + * 可以为注解操作所生成的api结果 + * @return List 泛型结果集合:用于返回解析后的结果集合 + * @exception + */ + List generateDoc(I param); + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanBaseObject.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanBaseObject.java new file mode 100644 index 0000000..f653eed --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanBaseObject.java @@ -0,0 +1,60 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.bean; + +import com.hyts.apidoc.annotation.Api; + +/** + * @title ScanBaseObject.java + * @package com.hyts.apidoc.bean + * @description 市面上基础的扫描机制服务对象 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +@Api +public class ScanBaseObject { + + /** + *

+ * 扫描的包的集合,包和包之间必须进行严格控制,尽量不要进行交叉否则会引起重复扫描 + * TODO 待优化 + *

+ * @fieldName packages + * @fieldType String[] + */ + public String[] packages; + + /** + *

扫描范围为可以处于在Retention范畴:runtime的操作注解

+ * @fieldName annotations + * @fieldType Class[] + */ + public Class[] annotations; + + /** + *

+ * 排除扫描的包的集合,包和包之间必须进行严格控制,尽量不要进行交叉否则会引起重复扫描 + * TODO 待优化 + *

+ * @fieldName execludePackages + * @fieldType String[] + */ + public String[] excludePackages; + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanExtObject.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanExtObject.java new file mode 100644 index 0000000..090f683 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanExtObject.java @@ -0,0 +1,76 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.bean; + +import java.util.List; + +import com.hyts.apidoc.config.ScanRule; +import com.hyts.apidoc.config.ScanRuleConfig; + +/** + * @title ScanExtObject.java + * @package com.hyts.apidoc.bean + * @description 扫描信息扩展对象,进行扫描操作相关信息 + * 包含扫描的范围,扫描的条件以及扫描 + * 的力度,总体控制范围核心类对象 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public final class ScanExtObject extends ScanBaseObject{ + + /** + *

+ * 扫描类条件—01,扫描类需要继承的父类,因为但继承故此不需要进行多个类制定 + * 不支持多级父类的继承限制 + *

+ * @fieldName superClass + * @fieldType Class + */ + public Class superClass; + + /** + *

+ * 扫描控制机制:提供扫描规则控制针对于多个接口之间 + * 默认 {@link com.hyts.apidoc.config.ScanRuleConfig #DEFAULT_SUPER_CLASS_SCAN_RULE} + *

+ * @fieldName superInterfaceScanRule + * @fieldType ScanRule + */ + public ScanRule superClassScanRule = ScanRuleConfig.DEFAULT_SUPER_CLASS_SCAN_RULE; + + /** + *

扫描类条件—02,扫描类需要实现的接口,因为但实现故此需要进行多个接口制定 + * 不支持多级接口的实现限制

+ * @fieldName superInterfaceClass + * @fieldType List> + */ + public List> superInterfaceClass; + + /** + *

+ * 扫描控制机制:提供扫描规则控制针对于多个接口之间 + * 默认 {@link com.hyts.apidoc.config.ScanRuleConfig #DEFAULT_SUPER_INTERFACE_SCAN_RULE} + *

+ * @fieldName superInterfaceScanRule + * @fieldType ScanRule + */ + public ScanRule superInterfaceScanRule = ScanRuleConfig.DEFAULT_SUPER_INTERFACE_SCAN_RULE; + + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanResultObject.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanResultObject.java new file mode 100644 index 0000000..6cf3523 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/bean/ScanResultObject.java @@ -0,0 +1,104 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.bean; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +/** + * @title ScanResultObject.java + * @package com.hyts.apidoc.bean + * @description 扫描结果后的对象:包含所有种情况的操作服务 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class ScanResultObject { + + + /** + *

{字段的描述}

+ * @fieldName scanResultClass + * @fieldType List> + */ + public List> scanResultClass; + + + /** + *

{字段的描述}

+ * @fieldName scanResultFile + * @fieldType List + */ + public List scanResultFile; + + + + /** + * @constructor:ScanResultObject + */ + public ScanResultObject() { + super(); + scanResultClass = new LinkedList<>(); + scanResultFile = new LinkedList<>(); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanResultClass + * @exception + */ + public void addResultClass(List> scanResultClass){ + if(Objects.nonNull(scanResultClass) && !scanResultClass.isEmpty()) + this.scanResultClass.addAll(scanResultClass); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param clazz + * @exception + */ + public void addResultClass(Class clazz) { + scanResultClass.add(clazz); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanResultClass + * @exception + */ + public void addResultFile(List scanResultFile){ + if(Objects.nonNull(scanResultFile) && !scanResultFile.isEmpty()) + this.scanResultFile.addAll(scanResultFile); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param clazz + * @exception + */ + public void addResultFile(String filePath) { + scanResultFile.add(filePath); + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/AnalysisConfig.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/AnalysisConfig.java new file mode 100644 index 0000000..9ad7790 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/AnalysisConfig.java @@ -0,0 +1,106 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.config; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.springframework.util.CollectionUtils; + +import com.alibaba.fastjson.util.ServiceLoader; +import com.google.common.collect.Lists; +import com.hyts.apidoc.base.AnnotationDocConfig; + +/** + * @title AnalysisConfig.java + * @package com.hyts.apidoc.config + * @description + * 解析代码文档操作-系统规定解析标准 + * 所有解析对象都要以此对象为标准 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月24日 + * @version V1.0 + */ +public enum AnalysisConfig implements AnnotationDocConfig{ + + INSTANCE("this"), + /*********文件类型-头名称**************/ + EXT_TYPE_HEADER_TITLE_NAME("@title"),//EXT开头非官方标准要求 + EXT_TYPE_HEADER_TITLE_PACKAGE("@package"), + TYPE_HEADER_TITLE_DESC("@description"), + TYPE_HEADER_TITLE_AUTHOR("@author"), + EXT_TYPE_HEADER_TITLE_EMAIL("@email"), + TYPE_HEADER_TITLE_DATE("@date"), + TYPE_HEADER_TITLE_VERSION("@version"), + TYPE_HEADER_TITLE_SEE("@see"), + TYPE_HEADER_TITLE_PACKAGE("@package"), + //特别注释 + TYPE_ATTRIBUTE_OVERTIME("@deprecated"),//@Deprecated + + /*********方法-信息字段**************/ + METHOD_HEADER_EXCEPTION("@exception"), + METHOD_HEADER_THROWS("@throws"), + METHOD_HEADER_RETURN("@return"), + METHOD_HEADER_PARAM("@param"), + METHOD_HEADER_NAME("@name"); + + + public String code; + + /** + * @constructor:AnalysisConfig + * @param code + */ + private AnalysisConfig(String code) { + this.code = code; + } + + /** + * @name code's getter method + * @param none + * @return code + */ + public String getCode() { + return code; + } + + /** + * @name code's setter method + * @param code + * @return void + */ + public void setCode(String code) { + this.code = code; + } + + + public AnalysisConfig[] getValues() { + List annotationList = new LinkedList<>(); + Set serviceClass = ServiceLoader.load(AnnotationDocConfig.class, AnalysisConfig.class.getClassLoader()); + if(CollectionUtils.isEmpty(serviceClass)) { + return AnalysisConfig.values(); + } + for(AnnotationDocConfig config:serviceClass) { + annotationList.addAll(Arrays.asList(config.getValues())); + } + annotationList.addAll(Arrays.asList(AnalysisConfig.values())); + return annotationList.toArray(new AnalysisConfig[annotationList.size()]); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ParseDocType.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ParseDocType.java new file mode 100644 index 0000000..110a084 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ParseDocType.java @@ -0,0 +1,35 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.config; + +/** + * @title ParseDocType.java + * @package com.hyts.apidoc.config + * @description 解析以及生成的api doc文档的方法类型 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public enum ParseDocType { + + //java原生 + JAVADOC, + //swagger强大的apidoc文档 + SWAGGER, + //coffice-apidoc自带解析器 + APIDOC; +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRule.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRule.java new file mode 100644 index 0000000..7dc977a --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRule.java @@ -0,0 +1,35 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.config; + +/** + * @title ScanRule.java + * @package com.hyts.apidoc.config + * @description 扫描机制规则:定义接口规则,统一公共类规则定义 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public enum ScanRule { + + //且关系 + AND, + //或关系 + OR, + //对立关系 + NOT +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRuleConfig.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRuleConfig.java new file mode 100644 index 0000000..d53d9c0 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/config/ScanRuleConfig.java @@ -0,0 +1,45 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.config; + +/** + * @title ScanRuleConfig.java + * @package com.hyts.apidoc.config + * @description 扫描规则控制配置类:默认选项,约定优于配置原则 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public final class ScanRuleConfig { + + /** + *

默认扫描父接口的规则 且关系操作

+ * @fieldName DEFAULT_SUPER_INTERFACE_SCAN_RULE + * @fieldType ScanRule + */ + public static final ScanRule DEFAULT_SUPER_INTERFACE_SCAN_RULE = ScanRule.AND; + + /** + *

默认扫描父类的规则 且关系操作

+ * @fieldName DEFAULT_SUPER_INTERFACE_SCAN_RULE + * @fieldType ScanRule + */ + public static final ScanRule DEFAULT_SUPER_CLASS_SCAN_RULE = ScanRule.AND; + + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/error/ApiDocError.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/error/ApiDocError.java new file mode 100644 index 0000000..970a417 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/error/ApiDocError.java @@ -0,0 +1,68 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.error; + +/** + * @title ApiDocError.java + * @package com.hyts.apidoc.error + * @description Api文档操作总体运行时异常信息对象 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class ApiDocError extends RuntimeException { + + /** + *

串行化流水号

+ * @fieldName serialVersionUID + * @fieldType long + */ + private static final long serialVersionUID = 3893181152793571902L; + + /** + * @constructor:ApiDocError + */ + public ApiDocError() { + super(); + } + + /** + * @constructor:ApiDocError + * @param message + * @param cause + */ + public ApiDocError(String message, Throwable cause) { + super(message, cause); + } + + /** + * @constructor:ApiDocError + * @param message + */ + public ApiDocError(String message) { + super(message); + } + + /** + * @constructor:ApiDocError + * @param cause + */ + public ApiDocError(Throwable cause) { + super(cause); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocHandler.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocHandler.java new file mode 100644 index 0000000..92b1ddd --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.javadoc; + +import java.util.List; + +import com.hyts.apidoc.base.BaseApiParser; +import com.hyts.apidoc.config.ParseDocType; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.utility.ParserFactory; +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.RootDoc; + +/** + * @title JavaDocHandler.java + * @package com.hyts.apidoc.javadoc + * @description JavaDocHandler 基础解析类: + * 用于解析javadoc级别的系统解析文档信息 + * 得出最后的结果字段。 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public final class JavaDocHandler { + + /** + * start:默认启动方法 + *

解析和读取注释的核心方法

+ * @param root 回掉函数返回的参数 + * @return 是否成功解析 + * @exception + */ + public static boolean start(RootDoc root) { + ClassDoc[] classDocs = root.classes(); + //设置为JAVADOC方法解析操作 + ParserFactory.setDocType(ParseDocType.JAVADOC); + BaseApiParser parser = ParserFactory.getInstance(); + List docLists = parser.generateDoc(classDocs); + return true; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocSupport.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocSupport.java new file mode 100644 index 0000000..054ec5b --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/javadoc/JavaDocSupport.java @@ -0,0 +1,58 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.javadoc; + +import java.util.List; +import java.util.Objects; + +import com.hyts.apidoc.config.ApiDocConfig; +import com.sun.tools.javadoc.Main; + +/** + * @title JavaDocSupport.java + * @package com.hyts.apidoc.javadoc + * @description sun 官方支持的javadoc操作进行控制 + * javadoc的读取以及抽取实现方法,此处为支持系统操作 + * 控制工具 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public final class JavaDocSupport { + /** + * buildJavaDocParam + *

构建javadoc参数信息帮助类

+ * @param paramList + * @return String[] 字符串数组结果集合 + * @exception + */ + public static boolean buildJavaDocParam(List paramList){ + if(Objects.isNull(paramList) || paramList.isEmpty()) { + return false; + } + try { + paramList.add(0,ApiDocConfig.DEFAULT_SUN_JAVA_DOC);//Doclet方式解析Javadoc方案 + paramList.add(1,ApiDocConfig.DEFAULT_JAVA_DOC_HANDLER);//处理Javadoc操作句柄服务 + String[] results = paramList.toArray(new String[paramList.size()]); + Main.execute(results); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDefination.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDefination.java new file mode 100644 index 0000000..2deb7be --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDefination.java @@ -0,0 +1,195 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.model; + +import java.util.List; + +/** + * @title ApiDefination.java + * @package com.hyts.apidoc.model + * @description API文档单个接口的定义规则服务可以作为单个类中的单个接口定义类的方法 + * @see {@link ApiParam} 参数信息类 + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public final class ApiDefination { + + /** + *

包名称信息

+ * @fieldName packageName + * @fieldType String + */ + private String packageName; + + /** + *

api方法接口方法名称rest服务请求接口明

+ * @fieldName name + * @fieldType String + */ + private String name; + + /** + *

api方法描述信息

+ * @fieldName description + * @fieldType String + */ + private String description; + + /** + *

请求地址URL

+ * @fieldName requestUrl + * @fieldType String + */ + private String requestUrl; + + /** + *

请求参数列表

+ * @fieldName request + * @fieldType List + */ + private List inputParameters; + + /** + *

结果参数列表

+ * @fieldName outputParameters + * @fieldType List + */ + private List outputParameters; + + /** + *

捕获异常列表

+ * @fieldName outputParameters + * @fieldType List + */ + private List exceptionList; + + /** + * @name name's getter method + * @param none + * @return name + */ + public String getName() { + return name; + } + + /** + * @name name's setter method + * @param name + * @return void + */ + public void setName(String name) { + this.name = name; + } + + /** + * @name description's getter method + * @param none + * @return description + */ + public String getDescription() { + return description; + } + + /** + * @name description's setter method + * @param description + * @return void + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @name requestUrl's getter method + * @param none + * @return requestUrl + */ + public String getRequestUrl() { + return requestUrl; + } + + /** + * @name requestUrl's setter method + * @param requestUrl + * @return void + */ + public void setRequestUrl(String requestUrl) { + this.requestUrl = requestUrl; + } + + /** + * @name inputParameters's getter method + * @param none + * @return inputParameters + */ + public List getInputParameters() { + return inputParameters; + } + + /** + * @name inputParameters's setter method + * @param inputParameters + * @return void + */ + public void setInputParameters(List inputParameters) { + this.inputParameters = inputParameters; + } + + /** + * @name outputParameters's getter method + * @param none + * @return outputParameters + */ + public List getOutputParameters() { + return outputParameters; + } + + /** + * @name outputParameters's setter method + * @param outputParameters + * @return void + */ + public void setOutputParameters(List outputParameters) { + this.outputParameters = outputParameters; + } + + /** + * @name packageName's getter method + * @param none + * @return packageName + */ + public String getPackageName() { + return packageName; + } + + /** + * @name packageName's setter method + * @param packageName + * @return void + */ + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public List getExceptionList() { + return exceptionList; + } + + public void setExceptionList(List exceptionList) { + this.exceptionList = exceptionList; + } +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDoc.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDoc.java new file mode 100644 index 0000000..c8646d0 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiDoc.java @@ -0,0 +1,221 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.model; + +import java.util.List; + +/** + * @title ApiDoc.java + * @package com.hyts.apidoc.model + * @description API文档总体入口操作类 用于处理单次总体API文档的对象 + * @see {@link com.hyts.apidoc.model.ApiDefination} api模型核心对象 + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018-4-18 + * @version V1.0 + */ +public final class ApiDoc { + + /** + *

api类级别文档的名称:用于作为一个全局的名称-可以作为一个类名称:也可以自定义名称

+ * @fieldName apiTypeName + * @fieldType String + */ + private String apiTypeName; + + /** + *

{字段的描述}

+ * @fieldName author + * @fieldType String + */ + private String author; + + /** + *

{字段的描述}

+ * @fieldName date + * @fieldType String + */ + private String date; + + /** + *

{字段的描述}

+ * @fieldName version + * @fieldType String + */ + private String version; + + /** + *

api文档信息描述

+ * @fieldName apiDescription + * @fieldType String + */ + private String apiDescription; + + /** + *

{字段的描述}

+ * @fieldName packageName + * @fieldType String + */ + private String packageName; + + /** + *

api文档定义列表一个type内部的-类type

+ * @fieldName apiDefinationList + * @fieldType List + */ + private List apiDefinationList; + + /** + * @name apiTypeName's getter method + * @param none + * @return apiTypeName + */ + public String getApiTypeName() { + return apiTypeName; + } + + /** + * @name apiTypeName's setter method + * @param apiTypeName + * @return void + */ + public void setApiTypeName(String apiTypeName) { + this.apiTypeName = apiTypeName; + } + + /** + * @name apiDefinationList's getter method + * @param none + * @return apiDefinationList + */ + public List getApiDefinationList() { + return apiDefinationList; + } + + /** + * @name apiDefinationList's setter method + * @param apiDefinationList + * @return void + */ + public void setApiDefinationList(List apiDefinationList) { + this.apiDefinationList = apiDefinationList; + } + + /** + * @name apiDescription's getter method + * @param none + * @return apiDescription + */ + public String getApiDescription() { + return apiDescription; + } + + /** + * @name apiDescription's setter method + * @param apiDescription + * @return void + */ + public void setApiDescription(String apiDescription) { + this.apiDescription = apiDescription; + } + + /** + * @name author's getter method + * @param none + * @return author + */ + public String getAuthor() { + return author; + } + + /** + * @name author's setter method + * @param author + * @return void + */ + public void setAuthor(String author) { + this.author = author; + } + + /** + * @name date's getter method + * @param none + * @return date + */ + public String getDate() { + return date; + } + + /** + * @name date's setter method + * @param date + * @return void + */ + public void setDate(String date) { + this.date = date; + } + + /** + * @name version's getter method + * @param none + * @return version + */ + public String getVersion() { + return version; + } + + /** + * @name version's setter method + * @param version + * @return void + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * @name packageName's getter method + * @param none + * @return packageName + */ + public String getPackageName() { + return packageName; + } + + /** + * @name packageName's setter method + * @param packageName + * @return void + */ + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- toString + *

TODO(这里用一句话描述这个方法的作用)

+ * @return + * @see java.lang.Object#toString() + * @exception + */ + + @Override + public String toString() { + return "ApiDoc [apiTypeName=" + apiTypeName + ", author=" + author + ", date=" + date + ", version=" + version + + ", apiDescription=" + apiDescription + ", packageName=" + packageName + ", apiDefinationList=" + + apiDefinationList + "]"; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiParam.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiParam.java new file mode 100644 index 0000000..090a31d --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/model/ApiParam.java @@ -0,0 +1,129 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.model; + +/** + * @title ApiParam.java + * @package com.hyts.apidoc.model + * @description API接口操作参数信息:输入参数和输出参数保持一直的数据结构 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class ApiParam { + + /** + *

参数名称

+ * @fieldName paramName + * @fieldType String + */ + private String paramName; + + /** + *

参数类型

+ * @fieldName paramType + * @fieldType String + */ + private String paramType; + + /** + *

参数描述

+ * @fieldName paramDescription + * @fieldType String + */ + private String paramDescription; + + /** + *

是否必填项

+ * @fieldName isRequired + * @fieldType String + */ + private String isRequired; + + /** + * @name paramName's getter method + * @param none + * @return paramName + */ + public String getParamName() { + return paramName; + } + + /** + * @name paramName's setter method + * @param paramName + * @return void + */ + public void setParamName(String paramName) { + this.paramName = paramName; + } + + /** + * @name paramType's getter method + * @param none + * @return paramType + */ + public String getParamType() { + return paramType; + } + + /** + * @name paramType's setter method + * @param paramType + * @return void + */ + public void setParamType(String paramType) { + this.paramType = paramType; + } + + /** + * @name paramDescription's getter method + * @param none + * @return paramDescription + */ + public String getParamDescription() { + return paramDescription; + } + + /** + * @name paramDescription's setter method + * @param paramDescription + * @return void + */ + public void setParamDescription(String paramDescription) { + this.paramDescription = paramDescription; + } + + /** + * @name isRequired's getter method + * @param none + * @return isRequired + */ + public String getIsRequired() { + return isRequired; + } + + /** + * @name isRequired's setter method + * @param isRequired + * @return void + */ + public void setIsRequired(String isRequired) { + this.isRequired = isRequired; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/AnnotationApiParser.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/AnnotationApiParser.java new file mode 100644 index 0000000..b4a02d9 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/AnnotationApiParser.java @@ -0,0 +1,48 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.parser; + +import java.util.List; + +import com.hyts.apidoc.base.BaseApiParser; + +/** + * @title AnnotationApiParser.java + * @package com.hyts.apidoc.parser + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class AnnotationApiParser implements BaseApiParser{ + + /* (非 Javadoc) + * TODO(方法功能的描述)- generateDoc + *

TODO(这里用一句话描述这个方法的作用)

+ * @param param + * @return + * @see com.hyts.apidoc.base.BaseApiParser#generateDoc(java.lang.Object) + * @exception + */ + + @Override + public List generateDoc(Object param) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/JavaDocApiParser.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/JavaDocApiParser.java new file mode 100644 index 0000000..804b7d2 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/JavaDocApiParser.java @@ -0,0 +1,98 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.parser; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import org.springframework.util.StringUtils; + +import com.hyts.apidoc.analysis.AnalysisEngine; +import com.hyts.apidoc.base.BaseApiParser; +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.javadoc.JavaDocSupport; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.scanner.SourceScanner; +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.MethodDoc; + +/** + * @title JavaDocApiParser.java + * @package com.hyts.apidoc.parser + * @description JavaDoc操作处理生成的class信息 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class JavaDocApiParser implements BaseApiParser{ + + + static List apiDocList = new LinkedList<>(); + + + /* (非 Javadoc) + * 实现方法- generateDoc + *

generateDoc

+ * @param param ClassDoc文档集合 + * @return + * @see com.hyts.apidoc.base.BaseApiParser#generateDoc(java.lang.Object) + * @exception + */ + @Override + public List generateDoc(ClassDoc[] param) { + //List apiDocs = new LinkedList(); + for(ClassDoc doc:param) { + //操作对应的type级别的javadoc注释 + ApiDoc apiDoc = AnalysisEngine.analysisTypeHeader(doc.tags()); + if(StringUtils.isEmpty(apiDoc.getPackageName())) { + apiDoc.setPackageName(StringUtils.replace(doc.qualifiedName(),"."+doc.name(),"")); + } + if(StringUtils.isEmpty(apiDoc.getApiTypeName())) { + apiDoc.setApiTypeName(doc.name()); + } + for (MethodDoc methodDoc : doc.methods()) { + System.out.println(methodDoc.name()); + System.out.println(methodDoc.returnType().getElementType()); + System.out.println(methodDoc.modifiers()); + System.out.println(methodDoc.thrownExceptionTypes()[0].typeName()); + System.out.println(methodDoc.parameters()[0].name()); + System.out.println(methodDoc.parameters()[0].typeName()); + apiDoc = AnalysisEngine.analysisMethodHeader(methodDoc.tags(),apiDoc); + } + apiDocList.add(apiDoc); + } + return apiDocList; + } + + /** + * 执行解析文档生产文档操作 + * @param scanBaseObject + * @return + * @exception + */ + public List execute(ScanBaseObject scanBaseObject) { + JavaDocSupport.buildJavaDocParam(new SourceScanner(true).scan(scanBaseObject).scanResultFile); + return apiDocList; + } + + public static List getApiDocList() { + return apiDocList; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/SwaggerApiParser.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/SwaggerApiParser.java new file mode 100644 index 0000000..fa09f94 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/parser/SwaggerApiParser.java @@ -0,0 +1,48 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.parser; + +import java.util.List; + +import com.hyts.apidoc.base.BaseApiParser; + +/** + * @title SwaggerApiParser.java + * @package com.hyts.apidoc.parser + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class SwaggerApiParser implements BaseApiParser { + + /* (非 Javadoc) + * TODO(方法功能的描述)- generateDoc + *

TODO(这里用一句话描述这个方法的作用)

+ * @param param + * @return + * @see com.hyts.apidoc.base.BaseApiParser#generateDoc(java.lang.Object) + * @exception + */ + + @Override + public List generateDoc(String param) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/JarScanner.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/JarScanner.java new file mode 100644 index 0000000..479d6ce --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/JarScanner.java @@ -0,0 +1,100 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import com.hyts.apidoc.base.AbstractScanner; +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanExtObject; +import com.hyts.apidoc.bean.ScanResultObject; +import com.hyts.apidoc.scanner.help.AnnotationHelper; +import com.hyts.apidoc.scanner.help.ClassHelper; +import com.hyts.apidoc.scanner.help.ScanHelper; + +/** + * @title JarScanner.java + * @package com.hyts.apidoc.scanner + * @description jar包相关的扫描机制,专属扫描jar内,匹配此包结构的相关类, + * 默认扫描所有相关的机械性扫描类,可以控制扫描范围,扫描机制 + * 递归,且可以根据系统提供相关的注解、继承类进行深层限制和控 + * 制范围 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class JarScanner extends AbstractScanner{ + + /** + *

是否递归

+ * @fieldName isRecursive + * @fieldType boolean + */ + private boolean isRecursive; + + /** + * @constructor:SourceScanner + * @param isRecursive + */ + public JarScanner(boolean isRecursive) { + super(); + this.isRecursive = isRecursive; + } + + /** + * @constructor:SourceScanner + */ + public JarScanner() { + super(); + this.isRecursive = true; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- scan + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanObject + * @return + * @see com.hyts.apidoc.base.AbstractScanner#scan(com.hyts.apidoc.bean.ScanBaseObject) + * @exception + */ + @Override + public ScanResultObject scan(ScanBaseObject scanObject) { + //判断属于那种解析操作,系统自动识别-进行切换扫描复杂度 + ScanResultObject result = new ScanResultObject(); + if(scanObject instanceof ScanBaseObject) { + List resultFileList= isRecursive? + new ScanHelper().scanRecursive(scanObject):new ScanHelper().scanNonRecursive(scanObject); + for(String filePath:resultFileList) { + Class clazz = ClassHelper.filePathToClass(filePath, scanObject.packages); + if(Objects.nonNull(scanObject.annotations) && scanObject.annotations.length != 0) { + if(Stream.of(scanObject.annotations).anyMatch(param->AnnotationHelper.isContainAnnotation(clazz, param))) { + result.addResultClass(clazz); + } + }else { + result.addResultClass(clazz); + } + } + }else if(scanObject instanceof ScanExtObject){ + ScanExtObject newScanObject = (ScanExtObject)scanObject; + } + return result; + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/Scanner.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/Scanner.java new file mode 100644 index 0000000..447f081 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/Scanner.java @@ -0,0 +1,111 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner; + +import java.util.Objects; +import java.util.Optional; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanResultObject; + + + +/** + * @title PackageScanner.java + * @package com.hyts.apidoc.scanner + * @description package 系统所有包的扫描类:扫描所有相关的文件类 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class Scanner { + + /** + *

{字段的描述}

+ * @fieldName jarScanner + * @fieldType JarScanner + */ + private JarScanner jarScanner; + + /** + *

{字段的描述}

+ * @fieldName sourceScanner + * @fieldType SourceScanner + */ + private SourceScanner sourceScanner; + + /** + *

扫描对象

+ * @fieldName scanObject + * @fieldType ScanBaseObject + */ + private ScanBaseObject scanObject; + + /** + * @constructor:Scanner + * @param jarScanner + * @param sourceScanner + */ + public Scanner(ScanBaseObject obj) { + this.jarScanner = new JarScanner(); + this.sourceScanner = new SourceScanner(); + this.scanObject = obj; + } + + /** + * @constructor:Scanner + * @param sourceScanner + */ + public Scanner(ScanBaseObject obj,SourceScanner sourceScanner) { + super(); + this.sourceScanner = sourceScanner; + this.scanObject = obj; + } + + /** + * @constructor:Scanner + * @param jarScanner + */ + public Scanner(ScanBaseObject obj,JarScanner jarScanner) { + super(); + this.jarScanner = jarScanner; + this.scanObject = obj; + } + + /** + * scan:扫描服务对象信息 + *

扫描信息服务对象

+ * @return ScanResultObject + * @exception + */ + public ScanResultObject scan() { + ScanResultObject result = null; + //检测进行扫描构建扫描器-只扫描jar包的源代码 + if(Objects.nonNull(this.jarScanner)) { + result = jarScanner.scan(this.scanObject); + } + //检测进行构建扫描扫描器-项目内部文件源代码(不包含jar包中的文件) + if(Objects.nonNull(this.sourceScanner)) { + if(result == null) + result = new ScanResultObject(); + result.addResultClass(this.sourceScanner.scan(this.scanObject).scanResultClass); + result.addResultFile(this.sourceScanner.scan(this.scanObject).scanResultFile); + } + return result; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/SourceScanner.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/SourceScanner.java new file mode 100644 index 0000000..d48254f --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/SourceScanner.java @@ -0,0 +1,99 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import com.hyts.apidoc.base.AbstractScanner; +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanExtObject; +import com.hyts.apidoc.bean.ScanResultObject; +import com.hyts.apidoc.scanner.help.AnnotationHelper; +import com.hyts.apidoc.scanner.help.ClassHelper; +import com.hyts.apidoc.scanner.help.ScanHelper; + +/** + * @title SourceScanner.java + * @package com.hyts.apidoc.scanner + * @description source代码相关的扫描机制,专属扫描source源码内,匹配此包结构的相关类, + * 默认扫描所有相关的机械性扫描类,可以控制扫描范围,扫描机制 + * 递归,且可以根据系统提供相关的注解、继承类进行深层限制和控 + * 制范围 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class SourceScanner extends AbstractScanner{ + + + /** + *

是否递归

+ * @fieldName isRecursive + * @fieldType boolean + */ + private boolean isRecursive; + + /** + * @constructor:SourceScanner + * @param isRecursive + */ + public SourceScanner(boolean isRecursive) { + super(); + this.isRecursive = isRecursive; + } + + /** + * @constructor:SourceScanner + */ + public SourceScanner() { + super(); + this.isRecursive = true; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- scan + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanObject + * @return + * @see com.hyts.apidoc.base.AbstractScanner#scan(com.hyts.apidoc.bean.ScanBaseObject) + * @exception + */ + @Override + public ScanResultObject scan(ScanBaseObject scanObject) { + //判断属于那种解析操作,系统自动识别-进行切换扫描复杂度 + ScanResultObject result = new ScanResultObject(); + if(scanObject instanceof ScanBaseObject) { + List resultFileList= isRecursive? + new ScanHelper().scanRecursive(scanObject):new ScanHelper().scanNonRecursive(scanObject); + for(String filePath:resultFileList) { + String filePath2 = ClassHelper.filePathToUserPath(filePath, scanObject.packages); + result.addResultFile(filePath2); + Class className = ClassHelper.filePathToClass(filePath, scanObject.packages); + result.addResultClass(className); + } + }else if(scanObject instanceof ScanExtObject){ + ScanExtObject newScanObject = (ScanExtObject)scanObject; + } + return result; + } + + + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassFilter.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassFilter.java new file mode 100644 index 0000000..055b776 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassFilter.java @@ -0,0 +1,47 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner.filter; + +import java.io.File; +import java.io.FileFilter; + +/** + * @title ClassFilter.java + * @package com.hyts.apidoc.scanner.filter + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月20日 + * @version V1.0 + */ +public class ClassFilter implements FileFilter{ + + /* (非 Javadoc) + * TODO(方法功能的描述)- accept + *

TODO(这里用一句话描述这个方法的作用)

+ * @param pathname + * @return + * @see java.io.FileFilter#accept(java.io.File) + * @exception + */ + + @Override + public boolean accept(File pathname) { + System.out.println(pathname); + return true; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassNameFilter.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassNameFilter.java new file mode 100644 index 0000000..ab02606 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/filter/ClassNameFilter.java @@ -0,0 +1,80 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner.filter; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanExtObject; +import com.hyts.apidoc.utility.PathUtils; + +/** + * @title ClassFilter.java + * @package com.hyts.apidoc.scanner.filter + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class ClassNameFilter implements FilenameFilter { + + + /** + *

{字段的描述}

+ * @fieldName excludePackages + * @fieldType String[] + */ + private String[] excludePackages; + + /** + * @constructor:ClassFilter + * @param obj + */ + public ClassNameFilter(String[] excludePackages) { + this.excludePackages = excludePackages; + } + + /* + * TODO(方法功能的描述)- accept + *

TODO(这里用一句话描述这个方法的作用)

+ * @param dir + * @param name + * @return + * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String) + * @exception + */ + @Override + public boolean accept(File dir, String name) { + boolean skipFlag = true; + if(Objects.nonNull(excludePackages) && excludePackages.length != 0) { + skipFlag = Stream.of(excludePackages). + noneMatch(packageName -> + dir.getPath().contains(PathUtils.package2Path(packageName))); + } + return skipFlag && !name.contains("$"); + } + + + public static void main(String[] args) { + System.out.println(System.getProperty("user.dir")); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/AnnotationHelper.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/AnnotationHelper.java new file mode 100644 index 0000000..36d5421 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/AnnotationHelper.java @@ -0,0 +1,85 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner.help; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; + +/** + * @title AnnotationHelper.java + * @package com.hyts.apidoc.scanner.help + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月20日 + * @version V1.0 + */ +public final class AnnotationHelper { + + /** + * isContainAnnotation + *

是否包含注解

+ * @param scanClazz + * @param annotationClazz + * @return boolean 是否包含注解 + * @exception + */ + public static boolean isContainAnnotation(Class scanClazz,Class annotationClazz) { + return scanClazz.isAnnotationPresent(annotationClazz); + } + + /** + * getAnnotationByField + *

获取所有定义Field字段上的注解

+ * @param scanClazz + * @param annotationClazz + * @return Annotation[] + * @exception + */ + public static Annotation[] getAnnotationByField(Class scanClazz,Class annotationClazz) { + Field[] fields = scanClazz.getClass().getDeclaredFields(); + for(Field field : fields) { + field.getAnnotation(annotationClazz); + } + return null; + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanClazz + * @param annotationClazz + * @return + * @exception + */ + public static Annotation[] getAnnotationByMethod(Class scanClazz,Class annotationClazz) { + return null; + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param scanClazz + * @param annotationClazz + * @return + * @exception + */ + public static Annotation[] getAnnotationByType(Class scanClazz,Class annotationClazz) { + return null; + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ClassHelper.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ClassHelper.java new file mode 100644 index 0000000..e711a55 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ClassHelper.java @@ -0,0 +1,138 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner.help; + +import java.io.File; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import com.hyts.apidoc.config.ApiDocConfig; +import com.hyts.apidoc.utility.PathUtils; +import com.hyts.apidoc.utility.StringUtils; + +/** + * @title ClassHelper.java + * @package com.hyts.apidoc.scanner.help + * @description TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月20日 + * @version V1.0 + */ +public final class ClassHelper { + + /** + * 基础操作类 + */ + static Function getBasePackage = (param) ->{ + if(StringUtils.isNotBlank(param)) { + //肯定为基包 + if(param.indexOf(".") < 0) { + return param; + }else{ + //获取基包 + return param.substring(0,param.indexOf(".")); + } + } + return ""; + }; + + /** + * filePathToClass + *

文件路径直接转换为class加载器类

+ * @param filePath + * @param packages + * @return + * @exception + */ + public static Class filePathToClass(String filePath,String[] packages) { + //遍历基础包 + for(String packageName:packages) { + if(filePath.contains(PathUtils.package2Path(packageName))) { + String classPath = filePath.substring(filePath.indexOf(PathUtils.package2Path(packageName))); + try { + return Class.forName(PathUtils.path2Package(classPath). + substring(0,PathUtils.path2Package(classPath).lastIndexOf("."))); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + } + } + return null; + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param filePath + * @param packages + * @return + * @exception + */ + public static String filePathToUserPath(String filePath,String[] packages) { + //操作用户基础路径 + filePath = filePath.replace(File.separator,"/"); + for(String packageName:packages) { + String packageNamePath = packageName.replace(".","/"); + if(filePath.contains(packageNamePath)) { + StringBuilder path = new StringBuilder(); + int index = filePath. + indexOf(ApiDocConfig.DEFAULT_CLASS_COMPILEED_MAIN_PATH_SUBFIX)>-1?filePath. + indexOf(ApiDocConfig.DEFAULT_CLASS_COMPILEED_MAIN_PATH_SUBFIX):filePath. + indexOf(ApiDocConfig.DEFAULT_CLASS_COMPILED_TEST_PATH_SUBFIX); + String dealFilePath = filePath.substring(0,index+1); + path.append(dealFilePath). + //path.append(ApiDocConfig.DEFAULT_PROJECT_USER_PATH). + append("/"). + append(switchCompilePath(filePath)). + append(filePath.substring(filePath.indexOf(packageNamePath))); + return path.toString().replace(".class",".java"); + } + } + return null; + } + + /** + * 选择编译后的路径 + * @param filePath + * @return + * @exception + */ + private static final String switchCompilePath(String filePath) { + return filePath.indexOf(ApiDocConfig.DEFAULT_CLASS_COMPILEED_MAIN_PATH_SUBFIX)>-1?ApiDocConfig.DEFAULT_PROJECT_TYPE_BASE:ApiDocConfig.DEFAULT_PROJECT_TYPE_TEST; + } + + /** + * findBasePackage + *

获取基础包

+ * @param packages + * @return + * @exception + */ + public static Stream findBasePackage(String[] packages) { + //长度排序 且进行去重 + return Stream.of(packages)/*.sorted((param1, param2) -> param1.length() - param2.length())*/ + .map(getBasePackage).distinct(); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ScanHelper.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ScanHelper.java new file mode 100644 index 0000000..c57ca9f --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/scanner/help/ScanHelper.java @@ -0,0 +1,138 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.scanner.help; + +import java.io.File; +import java.net.URLDecoder; +import java.nio.file.Paths; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.scanner.filter.ClassFilter; +import com.hyts.apidoc.scanner.filter.ClassNameFilter; +import com.hyts.apidoc.utility.PathUtils; + +/** + * @title ScanHelper.java + * @package com.hyts.apidoc.scanner.help + * @description 扫描服务帮助类-用于处理扫描服务文件、class类信息 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public final class ScanHelper { + + + /** + *

扫描的结果集合

+ * @fieldName scanClassList + * @fieldType List + */ + List scanClassList = new LinkedList<>(); + + /***********************scan帮助类-单元操作类****start*****************************************/ + + /** + * scanRecursive:递归单元操作 + *

递归选择文件遍历操作

+ * @param filePath 当前待文件路径-主要为文件夹-文件则会出现问题,暂时不错处理 + * @param excludePackages + * @return 返回java class类文件集合 + */ + List scanRecursive(String filePath,String[] excludePackages){ + File file = new File(filePath); + File[] childFiles = file.listFiles(new ClassNameFilter(excludePackages)); + for(File childFile:childFiles) { + if(childFile.isDirectory()) { + scanRecursive(childFile.getPath(),excludePackages); + }else { + scanClassList.add(childFile.getPath()); + } + } + return this.scanClassList; + } + + /** + * scanNonRecursive:非递归单元操作 + *

非递归选择文件遍历操作

+ * @param filePath 当前待文件路径-主要为文件夹-文件则会出现问题,暂时不错处理 + * @param excludePackages + * @return 返回java class类文件集合 + */ + List scanNonRecursive(String filePath,String[] excludePackages){ + File file = new File(filePath); + LinkedList directoryClassList = new LinkedList<>(); + if(file.isFile()) { + scanClassList.add(file.getPath()); + return scanClassList; + } + File[] childFiles = file.listFiles(new ClassNameFilter(excludePackages)); + for(File childFile:childFiles) { + if(childFile.isDirectory()) { + directoryClassList.add(childFile.getPath()); + }else { + scanClassList.add(childFile.getPath()); + } + } + for(;!directoryClassList.isEmpty();) { + File directoryPath = new File(directoryClassList.removeFirst()); + File[] childFile2 = directoryPath.listFiles(new ClassNameFilter(excludePackages)); + for(File childFile:childFile2) { + if(childFile.isDirectory()) { + directoryClassList.add(childFile.getPath()); + }else { + scanClassList.add(childFile.getPath()); + } + } + } + return scanClassList; + } + + + /***********************scan帮助类-单元操作类****end*****************************************/ + + /** + * scan2Recursive + *

扫描包根据递归方案

+ * @param 包路径:初始化包路径 + */ + public List scanRecursive(ScanBaseObject obj) { + if(Objects.nonNull(obj.packages) && obj.packages.length != 0) { + Stream.of(obj.packages).forEach(packageName->{ + scanRecursive(PathUtils.package2FilePath(packageName),obj.excludePackages); + }); + } + return this.scanClassList; + } + + /** + * scan2NotRecursive + *

扫描包根据非递归方案

+ */ + public List scanNonRecursive(ScanBaseObject obj) { + if(Objects.nonNull(obj.packages) && obj.packages.length != 0) { + Stream.of(obj.packages).forEach(packageName->{ + scanNonRecursive(PathUtils.package2FilePath(packageName),obj.excludePackages); + }); + } + return this.scanClassList; + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/servlet/ApiDocServlet.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/servlet/ApiDocServlet.java new file mode 100644 index 0000000..6546b4a --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/servlet/ApiDocServlet.java @@ -0,0 +1,202 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.servlet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.util.CollectionUtils; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanResultObject; +import com.hyts.apidoc.javadoc.JavaDocSupport; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.parser.JavaDocApiParser; +import com.hyts.apidoc.scanner.SourceScanner; +import com.hyts.apidoc.template.TemplateDataHandler; +import com.hyts.apidoc.template.TemplateInitHandler; +import com.hyts.apidoc.utility.StringUtils; +import com.hyts.template.freemarker.FreemarkerContext; +import com.hyts.template.freemarker.FreemarkerStream; +import com.hyts.template.freemarker.FreemarkerTemplate; + +/** + * @author LiBo/Alex + * @version V1.0 + */ +public class ApiDocServlet extends HttpServlet{ + + private String apiDocPackage; + + /** + * @fieldName serialVersionUID + * @fieldType long + */ + private static final long serialVersionUID = -7985712981033737556L; + + //private static final String DEFAULT_API_DOC_SERVLET_PACKAGE_KEY = "apiScanPackage"; + + static List apiDocList = null; + + /** + * data index page + */ + private static final String DEFAULT_API_SERVLET_INDEX_PATH = "/index"; + + /** + * data detail page + */ + private static final String DEFAULT_API_SERVLET_DATA_PATH = "/detail"; + + /** + * data list page + */ + private static final String DEFAULT_API_SERVLET_LIST_PATH = "/list"; + + + private static final String DEFAULT_API_TEMPLATE_BASE_PATH = "/META-INF/resources/apidoc/"; + + + public static final String[] DEFAULT_SERVLET_MAPPINGS = {"/apidoc/index","/apidoc/detail","/apidoc/list"}; + + + public static final int DEFAULT_PAGE_SIZE = 10; + + public static final int DEFAULT_PAGE_INDEX = 6; + + /** + * @fieldName printer + * @fieldType FreemarkerStream> + */ + FreemarkerStream> printer = null; + + /** + * @fieldName dataMap + * @fieldType Map> + */ + private static Map> dataMap = null; + + + @Override + public void init() throws ServletException { + String apiDocPackageName = apiDocPackage;//getServletConfig().getInitParameter(DEFAULT_API_DOC_SERVLET_PACKAGE_KEY); + if(CollectionUtils.isEmpty(dataMap)) { + TemplateInitHandler.init(apiDocPackageName); + } + printer = new FreemarkerStream>(new FreemarkerContext() + .createContext(ApiDocServlet.class,DEFAULT_API_TEMPLATE_BASE_PATH)); + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + //request 请求操作 + if(req.getRequestURI().indexOf(DEFAULT_API_SERVLET_INDEX_PATH) > -1) { + index(req,resp); + }else if(req.getRequestURI().indexOf(DEFAULT_API_SERVLET_DATA_PATH)>-1) { + detail(req,resp); + }else if(req.getRequestURI().indexOf(DEFAULT_API_SERVLET_LIST_PATH)>-1) { + list(req,resp); + }else { + req.getRequestDispatcher(req.getRequestURI()).forward(req, resp); + } + } + + /** + * @throws IOException + * @param req + * @param resp + * @exception + */ + public void index(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/html;charset=UTF-8"); + HashMap param = new HashMap<>(); + param.put("contextPath", req.getContextPath()); + dataMap = TemplateDataHandler.countApiDocList(); + List dataList = new ArrayList<>(dataMap.keySet()); + param.put("packageList", dataList); + param.put("packageName",dataList.get(0)); + printer.writer("dataIndex.html",param,resp.getWriter()); + } + + /** + * @throws IOException + * @param req + * @param resp + * @exception + */ + public void detail(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/html;charset=UTF-8"); + HashMap param = new HashMap<>(); + String packageName = req.getParameter("packageName"); + List dataNum = dataMap.get(packageName); + param.put("packageName",packageName); + param.put("fileNum",dataNum.size()); + param.put("author","暂未开放此功能"); + param.put("createDate","暂未开放此功能"); + param.put("lastModifiedDate","暂未开放此功能"); + param.put("description","暂未开放此功能"); + param.put("projectName",req.getContextPath()); + param.put("contextPath", req.getContextPath()); + printer.writer("dataInfo.html",param,resp.getWriter()); + } + + + /** + * @throws IOException + * @param req + * @param resp + * @exception + */ + public void list(HttpServletRequest req, HttpServletResponse resp) throws IOException{ + resp.setContentType("text/html;charset=UTF-8"); + HashMap param = new HashMap<>(); + param.put("contextPath", req.getContextPath()); + String packageName = req.getParameter("packageName"); + int pageIndex = StringUtils.isBlank(req.getParameter("pageIndex"))?1: + Integer.parseInt(req.getParameter("pageIndex")); + List dataList = TemplateDataHandler.getClassDataListByPackageName(packageName); + int pageNum = TemplateDataHandler.pageNum(dataList); + List pageList = TemplateDataHandler.getPageIndexList(pageNum,pageIndex); + param.put("pageIndexList",pageList); + param.put("classList", TemplateDataHandler.getListByPage(dataList, pageIndex)); + param.put("packageName",packageName); + printer.writer("dataList.html",param,resp.getWriter()); + } + + public ApiDocServlet setApiDocPackage(String apiDocPackage) { + this.apiDocPackage = apiDocPackage; + return this; + } + + public static List getApiDocList() { + return apiDocList; + } + + public static void setApiDocList(List apiDocList) { + ApiDocServlet.apiDocList = apiDocList; + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocConfiguration.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocConfiguration.java new file mode 100644 index 0000000..bd04e1b --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.springboot; + +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; + +import com.hyts.apidoc.servlet.ApiDocServlet; + +/** + * @author LiBo/Alex + * @version V1.0 + */ +@AutoConfigureBefore(ApiDocServletConfiguration.class) +@Configuration +public class ApiDocConfiguration implements ImportBeanDefinitionRegistrar { + + + public static String annotationBasePackage = ""; + + /* (非 Javadoc) + * @param importingClassMetadata + * @param registry + * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) + * @exception + */ + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + AnnotationAttributes annotationAttri = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(InjectApiDoc.class.getName())); + annotationBasePackage = annotationAttri.getString("basePackage"); + } +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocServletConfiguration.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocServletConfiguration.java new file mode 100644 index 0000000..2e08945 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/springboot/ApiDocServletConfiguration.java @@ -0,0 +1,38 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.springboot; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.hyts.apidoc.servlet.ApiDocServlet; + +/** + * @author LiBo/Alex + * @version V1.0 + */ +@AutoConfigureAfter(ApiDocConfiguration.class) +@Configuration +public class ApiDocServletConfiguration { + + @Bean + public ServletRegistrationBean servletRegistrationBean() { + return new ServletRegistrationBean(new ApiDocServlet(). + setApiDocPackage(ApiDocConfiguration.annotationBasePackage),ApiDocServlet.DEFAULT_SERVLET_MAPPINGS); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateDataHandler.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateDataHandler.java new file mode 100644 index 0000000..f736f7d --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateDataHandler.java @@ -0,0 +1,205 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.template; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.common.collect.Lists; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.servlet.ApiDocServlet; +import com.hyts.apidoc.utility.StringUtils; +import com.sun.xml.internal.rngom.digested.DDataPattern.Param; + +import net.sf.cglib.core.CollectionUtils; + +/** + * @title TemplateHandler.java + * @package com.hyts.apidoc.template + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class TemplateDataHandler { + + /** + * 统计apidoc的package包的数据结构 @exception + */ + public static Map> countApiDocList() { + // 校验数据是否存在 + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return null; + } + // 操作apidoc服务功能 + Map> data = ApiDocServlet.getApiDocList().stream() + .collect(Collectors.groupingBy(ApiDoc::getPackageName)); + return data; + } + + /** + * 获取所有相关的package不为空的集合 @return @exception + */ + public static List getPackageNotNull() { + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return null; + } + return ApiDocServlet.getApiDocList().stream()/* + * . map(param->param.getPackageName()) + */.filter(param -> StringUtils.isNotBlank(param.getPackageName())) + .collect(Collectors.toList()); + } + + /** + * 获取所有相关的package为空的集合 @return @exception + */ + public static List getPackageNull() { + // 判断是否为空 + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return null; + } + return ApiDocServlet.getApiDocList().stream()/* + * . map(param->param.getPackageName()) + */.filter(param -> StringUtils.isBlank(param.getPackageName())) + .collect(Collectors.toList()); + } + + /** + * @return @exception + */ + public static List getClassNameNotNull() { + // 判断是否为空 + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return null; + } + return ApiDocServlet.getApiDocList().stream()/* + * . map(param->param.getPackageName()) + */.filter(param -> StringUtils.isNotBlank(param.getApiTypeName())) + .collect(Collectors.toList()); + } + + /** + * @return @exception + */ + public static List getClassNameNull() { + // 判断是否为空 + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return null; + } + return ApiDocServlet.getApiDocList().stream()/* + * . map(param->param.getPackageName()) + */.filter(param -> StringUtils.isBlank(param.getApiTypeName())) + .collect(Collectors.toList()); + } + + + /** + * @param apiDocList + * @param classList + * @exception + */ + public static void injectPackageName(List apiDocList,List> classList) { + apiDocList.stream().forEach(param->{ + classList.stream().forEach(param2->{ + String path = param.getApiTypeName(); + //重复名字且不同包会有问题 + if(StringUtils.isBlank(param.getPackageName())) { + if(path.contains(param2.getSimpleName()) || param2.getSimpleName().contains(path) + || path.equals(param2.getSimpleName())){ + param.setPackageName(param2.getPackage().getName()); + }else { + param.setPackageName("未定义包名!"); + } + } + }); + }); + } + + /** + * @param apiDocList + * @exception + */ + public static void injectClassName(List apiDocList) { + apiDocList.stream().forEach(param->{ + if(StringUtils.isEmpty(param.getApiTypeName())) + param.setApiTypeName("未定义类名称!"); + }); + } + + + public static List getClassDataListByPackageName(String packageName) { + if (ApiDocServlet.getApiDocList() == null || ApiDocServlet.getApiDocList().isEmpty()) { + System.err.println("无法进行相关apidoc的操作因为解析到的apiDocList数据为空!"); + return Collections.emptyList(); + } + return ApiDocServlet.getApiDocList().stream().filter(param->param.getPackageName().equals(packageName)).collect(Collectors.toList()); + } + + /** + * @return + * @exception + */ + public static List getListByPage(List dataList,int pageIndex){ + pageIndex = pageIndex <=0?1:pageIndex; + int skipNum = (pageIndex-1) * ApiDocServlet.DEFAULT_PAGE_SIZE; + return dataList.stream().skip(skipNum).limit(ApiDocServlet.DEFAULT_PAGE_SIZE) + .collect(Collectors.toList()); + } + + /** + * @param dataList + * @return + * @exception + */ + public static int pageNum(List dataList) { + int num = (dataList.size() / ApiDocServlet.DEFAULT_PAGE_SIZE); + return dataList.size() % ApiDocServlet.DEFAULT_PAGE_SIZE == 0 ? num:++num; + } + + /** + * @param pageNum 页总数-实际总数 + * @param pageIndex 页下标,当前请求的页下标 + * @return + * @exception + */ + public static List getPageIndexList(int pageNum,int pageIndex){ + int start = 1; + pageIndex = pageIndex <=0?1:pageIndex; + pageNum = pageNum <=0?1:pageNum; + int count = (pageNum>=pageIndex&&pageNum>ApiDocServlet.DEFAULT_PAGE_INDEX) + ?ApiDocServlet.DEFAULT_PAGE_INDEX:pageNum; + pageIndex = pageIndex == pageNum?pageIndex-1:pageIndex; + int num = (pageIndex - ApiDocServlet.DEFAULT_PAGE_INDEX)+1; + if(num >= 1) { + start+=num; + count+=num; + } + List pageIndexList = new LinkedList<>(); + for(int i = start ; i <=count ; i++) { + pageIndexList.add(i); + } + return pageIndexList; + } +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateInitHandler.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateInitHandler.java new file mode 100644 index 0000000..2f9891a --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/template/TemplateInitHandler.java @@ -0,0 +1,64 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.template; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.bean.ScanResultObject; +import com.hyts.apidoc.javadoc.JavaDocSupport; +import com.hyts.apidoc.model.ApiDoc; +import com.hyts.apidoc.parser.JavaDocApiParser; +import com.hyts.apidoc.scanner.SourceScanner; +import com.hyts.apidoc.servlet.ApiDocServlet; +import com.hyts.apidoc.utility.StringUtils; +import static com.hyts.apidoc.servlet.ApiDocServlet.setApiDocList; + +/** + * @author LiBo/Alex + * @version V1.0 + */ +public class TemplateInitHandler { + + /** + * @param apiDocPackageName + * @exception + */ + public static void init(String apiDocPackageName) { + if(StringUtils.isNotEmpty(apiDocPackageName)) { + ScanBaseObject scanBaseObject = new ScanBaseObject(); + scanBaseObject.packages = new String[] {apiDocPackageName}; + ScanResultObject obj = new SourceScanner(true).scan(scanBaseObject); + List file = obj.scanResultFile; + List> classFile = obj.scanResultClass; + JavaDocSupport.buildJavaDocParam(file); + setApiDocList(JavaDocApiParser.getApiDocList()); + //补充说明将为完成的数据进行补充说明功能主要补充为两点:class名称、package名称 + List dataApidocList = new LinkedList<>(); + List nullClassList = TemplateDataHandler.getClassNameNull(); + List notNullClassList = TemplateDataHandler.getPackageNotNull(); + TemplateDataHandler.injectClassName(nullClassList); + TemplateDataHandler.injectPackageName(nullClassList, classFile); + TemplateDataHandler.injectPackageName(notNullClassList, classFile); + dataApidocList.addAll(nullClassList); + dataApidocList.addAll(notNullClassList); + setApiDocList(dataApidocList); + } + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/ParserFactory.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/ParserFactory.java new file mode 100644 index 0000000..38c30e1 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/ParserFactory.java @@ -0,0 +1,146 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.utility; + +import java.util.Objects; + +import com.hyts.apidoc.base.BaseApiParser; +import com.hyts.apidoc.config.ParseDocType; +import com.hyts.apidoc.parser.AnnotationApiParser; +import com.hyts.apidoc.parser.JavaDocApiParser; +import com.hyts.apidoc.parser.SwaggerApiParser; + +/** + * @title ParserUtils.java + * @package com.hyts.apidoc.utility + * @description 解析操作工具类服务 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public final class ParserFactory { + + /** + *

{字段的描述}

+ * @fieldName docType + * @fieldType ParseDocType + */ + static ParseDocType docType = ParseDocType.JAVADOC; + + /** + *

{字段的描述}

+ * @fieldName parserLocal + * @fieldType ThreadLocal + */ + public static ThreadLocal parserLocal = new ThreadLocal() { + + /* (非 Javadoc) + * TODO(方法功能的描述)- initialValue + *

TODO(这里用一句话描述这个方法的作用)

+ * @return + * @see java.lang.ThreadLocal#initialValue() + * @exception + */ + @Override + protected BaseApiParser initialValue() { + this.set(newInstance()); + return this.get(); + } + }; + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @return + * @exception + */ + public static boolean clearParserSubject() { + try { + parserLocal.set(null); + parserLocal.remove(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * getInstance + *

枚举方案生成工厂类

+ * @param docType + * @return + * @exception + */ + private static BaseApiParser newInstance() { + switch(docType) { + case APIDOC: + return new AnnotationApiParser(); + case JAVADOC: + return new JavaDocApiParser(); + case SWAGGER: + return new SwaggerApiParser(); + default: + return new AnnotationApiParser(); + } + } + + /** + * getInstance + *

获取实例化对象

+ * @return + * @exception + */ + public static BaseApiParser getInstance() { + return parserLocal.get(); + } + + /** + * @name docType's setter method + * @param docType + * @return void + */ + public static void setDocType(ParseDocType docType) { + ParserFactory.docType = docType; + } + + /** + * @name docType's getter method + * @param none + * @return docType + */ + public static ParseDocType getDocType() { + return docType; + } + + + public static void main(String[] args) { + /*System.out.println(ParserFactory.getInstance()); + Thread newThread = new Thread(()->{ + ParserFactory.setDocType(ParseDocType.SWAGGER); + System.out.println(ParserFactory.getInstance()); + }); + newThread.start(); + try { + newThread.join(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }*/ + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PathUtils.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PathUtils.java new file mode 100644 index 0000000..5018324 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PathUtils.java @@ -0,0 +1,77 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.utility; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @title PathUtils.java + * @package com.hyts.apidoc.utility + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class PathUtils { + + /** + * package2Path + *

package包路径转换为path文件路径

+ * @param packagePath + * @return 转换后的文件路径 + * @exception + */ + public static String package2Path(String packagePath) { + return StringUtils.isNotBlank(packagePath)?packagePath.replace(".",File.separator):""; + } + + /** + * path2Package + *

path路径转换为package文件路径

+ * @param path + * @return 转换后的包路径 + * @exception + */ + public static String path2Package(String path) { + return StringUtils.isNotBlank(path)?path.replace(File.separator,"."):""; + } + + /** + * classPath2FilePath + *

classpath路径转为实际文件路径

+ * @param path + * @return + * @exception + */ + public static String classPath2FilePath(String path) { + return Thread.currentThread().getContextClassLoader().getResource(path).getPath(); + } + + /** + * package2FilePath + *

package路径转为实际文件路径

+ * @param path + * @return + * @exception + */ + public static String package2FilePath(String packagePath) { + return Thread.currentThread().getContextClassLoader().getResource(packagePath.replace(".", "/")).getPath(); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PropUtils.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PropUtils.java new file mode 100644 index 0000000..a26ad29 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/PropUtils.java @@ -0,0 +1,104 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.utility; + +import java.io.IOException; +import java.util.Properties; + +import com.hyts.apidoc.config.ApiDocConfig; + +/** + * @title PropUtils.java + * @package com.hyts.apidoc.utility + * @description 解析相关配置文件,读取配置文件工具类 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public final class PropUtils { + + /** + *

系统中唯一配置文件定义对象

+ * @fieldName prop + * @fieldType Properties + */ + private static Properties prop = null; + + /** + *

+ * 读取配置文件路径:默认为{@link com.hyts.apidoc.config.ApiDocConfig #DEFAULT_API_CONFIG_FILE} + * 字段默认值,可以 load方法修改默认读取文件操作,但只能在初始化之前修改,否则无效,而且同时只可以维护一个 + * 文件,切记。 + *

+ * @fieldName loadConfigPath + * @fieldType String + */ + private static String loadConfigPath = ApiDocConfig.DEFAULT_API_CONFIG_FILE; + + + //只执行一次-故此不需要进行判断是否为空操作与prop对象属于统一体 + static { + prop = new Properties(); + try { + prop.load(PropUtils.class.getClassLoader().getResourceAsStream(loadConfigPath)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * newInstance + *

构建静态properties对象

+ * @exception + */ + @Deprecated + public static void newInstance(){ + if(prop == null){ + synchronized(PropUtils.class) { + if(prop == null) { + prop = new Properties(); + } + } + } + } + + /** + * reload + *

重新切换读取配置文件操作

+ * @param configFile + * @exception + */ + public static void reload(String configFile) { + try { + prop.load(PropUtils.class.getClassLoader().getResourceAsStream(configFile)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * getValue + *

根据key获取value值

+ * @param key + * @return 对应的value值 + * @exception + */ + public static String getValue(String key) { + return prop.getProperty(key, ""); + } + +} diff --git a/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/StringUtils.java b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/StringUtils.java new file mode 100644 index 0000000..1588840 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/java/com/hyts/apidoc/utility/StringUtils.java @@ -0,0 +1,106 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.utility; + +/** + * @title StringUtils.java + * @package com.hyts.apidoc.utility + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月18日 + * @version V1.0 + */ +public class StringUtils { + + /** + * isNull:是否为空 + *

+ * 判断传入的字符串是否为空:只考虑:null一种条件 + * 如果考虑 (null,""、" "、等情况)请查看{@link #isEmpty(String)}方法 + * 如果考虑 (null,""、" "、"null"等情况)查看{@link #isBlank(String)}方法 + *

+ * @param paramStr 传入的字符换参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isNull(String paramStr) { + return paramStr == null; + } + + /** + * isNotNull:是否不为空 + *

+ * 判断传入的字符串是否不为空:只考虑:null一种条件 + * 如果考虑 (null,""、" "、等情况)请查看{@link #isNotEmpty(String)}方法 + * 如果考虑 (null,""、" "、"null"等情况)查看{@link #isNotBlank(String)}方法 + *

+ * @param paramStr 传入的字符换参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isNotNull(String paramStr) { + return paramStr != null; + } + + /** + * isEmpty:是否为空(字符串专业处理类) + *

判断是否字符串参数为空,进行判断是否属于空字符串操作 (null,""、" ") + * 如果考虑 (null,""、" "、"null"等情况)查看{@link #isBlank(String)}方法 + *

+ * @param paramStr 传入的字符串参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isEmpty(String paramStr) { + return isNull(paramStr) || "".equals(paramStr) || paramStr.trim().length() == 0; + } + + /** + * isNotEmpty:是否不为空(字符串专业处理类) + *

判断是否字符串参数不为空,进行判断是否不属于空字符串操作 (null,""、" ") + * 如果考虑 (null,""、" "、"null"等情况)查看{@link #isNotBlank(String)}方法 + *

+ * @param paramStr 传入的字符串参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isNotEmpty(String paramStr) { + return !isEmpty(paramStr); + } + + /** + * isBlank:判断是否为空(字符串最全面的的判断校验) + *

+ * 如果考虑 (null,""、" "、"null"等情况) + *

+ * @param paramStr 传入的字符串参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isBlank(String paramStr) { + return "null".equalsIgnoreCase(paramStr) || isEmpty(paramStr); + } + + /** + * isNotBlank:判断是否不为空(字符串最全面的的判断校验) + *

+ * 如果考虑 (null,""、" "、"null"等情况) + *

+ * @param paramStr 传入的字符串参数 + * @return 返回是否符合条件的boolean标识(true/false) + */ + public static boolean isNotBlank(String paramStr) { + return !isBlank(paramStr); + } + + +} diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/column.html b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/column.html new file mode 100644 index 0000000..2a376ba --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/column.html @@ -0,0 +1,193 @@ + + + + + + + + 网站信息 + + + + + + +
+
内容列表
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID栏目名称排序操作
17公司简介1 + +
17产品中心1 + +
17新闻资讯1 + +
17人才招聘1 + +
17联系我们1 + +
+
+ +
+
增加内容
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ + +
图片尺寸:1920*200
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + + +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/admin.css b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/admin.css new file mode 100644 index 0000000..637b04d --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/admin.css @@ -0,0 +1,78 @@ +body{ color:#333; font-size:13px;} +input,select,textarea{color:#333;} +.bg{ width:100%; height:100%; position:absolute; background:url(../images/bg.jpg) } +.panel{background:#fff;} +form .form-group:last-child{padding-bottom:0;} +.passcode{position:absolute;right:0;bottom:0;height:32px;margin:1px;border-left:solid 1px #ddd;text-align:center;line-height:32px;border-radius:0 4px 4px 0;} +ul,li{ list-style-type:none;} + +.lefter{position:relative;float:left;width:180px;margin-right:-180px;background:#e6f2fb;text-align:center;} +.righter{float:right;width:100%;padding-top:15px;background:#e6f2fb;} +.mainer{margin-left:180px;} +.field-icon-right .icon{ bottom:0px; top:auto} +.logo{ float:left; color:#FFF; margin-top:10px; line-height:45px;} +.logo img{ float:left; margin-right:10px;} +.loginbox { background:url(../images/tmbg-white.png); border:0px;} +/********头部******/ +.header{height:70px; overflow:hidden; background:url(../images/bg.jpg) no-repeat 0 -1000px; } +.head-l{ float:left; margin-top:17px; margin-left:15px; } +.head-l .button{ padding:8px 15px;} +.head-l .bg-blue:hover{ background-color:#03b6fd;} +.leftnav{width:180px; height:100%; position:fixed; top:70px; left:0px;} +.leftnav-title { height:50px; background:url(../images/bg.jpg) no-repeat 0 -1000px; color:#FFF; padding-left:22px; font-size:14px; line-height:50px;} +.leftnav-title span{ margin-right:10px;} +.leftnav h2{ padding:10px 0 10px 22px; transition:all .1s ease-in-out; display:block; cursor:pointer; font-weight:bold; font-size:14px; border-top:1px solid #b5cfd9;} +.leftnav h2.on{ color:#09c;} +.leftnav .border-bottom{ border-bottom:1px solid #b5cfd9;} +.leftnav h2 span{ margin-right:10px;} +.leftnav h2:hover{ color:#09c;} +.leftnav ul {display:none; border-top:1px solid #b5cfd9; padding:5px 0; opacity:1;} +.leftnav ul li{ list-style-type:none; } +.leftnav ul li a{ display:block;padding-left:30px;line-height:30px; } +.leftnav ul li span{ margin-right:8px;} +.leftnav ul li a:hover,.leftnav ul li a.on{ color:#09c;} + +/***主要内容***/ +.admin{background:#fff;position:fixed;border-left:solid 1px #b5cfd9;right:0;bottom:0;top:110px;left:180px; padding:15px; padding-right:0px; padding-bottom:0px; overflow:auto; border-top:1px solid #b5cfd9; padding-right:15px;} +.content{width:100%;} +.body-content{padding:20px 0; overflow:hidden;} +.content .title{ border-bottom:1px solid #dfdfdf; line-height:35px; font-size:14px; font-weight:bold; color:#09c} +.form-x .form-group .label{ width:10%;} +.form-x .form-button { margin-left:10%;} +.w50 { width:25%; float:left;} +.form-x .tipss{ float:left; padding-left:10px; color:#888; line-height:42px;} +.input-help { float:left; line-height:30px;} +.input-help li{ float:left;margin-left:10px;} +.bread{ margin-left:190px; margin-top:4px;} +.bread li{ float:left;} +.label label{ font-weight:normal; color:#333;} +.form-group{ margin-bottom:12px;} +.button{ padding:10px 15px;} +.form-group .field .file{ background:#FFF; border:0px;} +.form-group .field input[type=radio]{ vertical-align:middle; line-height:35px; margin-right:5px;} +.form-group .radio { line-height:35px;} +.table th{ text-align:center;} +.table td { vertical-align:middle;} +.tip img{width:100px; height:100px;} +.clear{ clear:both; overflow:hidden;} +.pagelist {padding:10px 0; text-align:center;} +.pagelist span,.pagelist a{ border-radius:3px; border:1px solid #dfdfdf;display:inline-block; padding:5px 12px;} +.pagelist a{ margin:0 3px;} +.pagelist span.current{ background:#09F; color:#FFF; border-color:#09F; margin:0 2px;} +.pagelist a:hover{background:#09F; color:#FFF; border-color:#09F; } +.pagelist label{ padding-left:15px; color:#999;} +.pagelist label b{color:red; font-weight:normal; margin:0 3px;} + +.search{ overflow:hidden;} +.search li{float:left; margin-right:15px; line-height:35px;} + +.button.bg-main.icon-check-square-o{ padding:10px 30px;} +.button.bg-main.icon-check-square-o:hover{ background:#08bbe1;} +input[type="checkbox"], input[type="radio"]{ width:15px; height:15px; vertical-align:-3px; margin-right:5px;} + +textarea[name=content]{width:100%; height:500px; border:1px solid #ddd; border-radius:3px; -webkit-border-radius:3px;} + + + + + diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/pintuer.css b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/pintuer.css new file mode 100644 index 0000000..755127d --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/css/pintuer.css @@ -0,0 +1,1083 @@ +html{margin:0;padding:0;border:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);} +body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, q, dl, dt, dd, ol, ul, li, fieldset, form, legend, caption, tbody, tfoot, thead, article, aside, dialog, figure, footer, header, hgroup, nav, section{margin:0;padding:0;border:0;font-size:14px;font:inherit;vertical-align:baseline;} +article, aside, details, figcaption, figure, dialog, footer, header, hgroup, menu, nav, section{display:block;} +body{font-size:14px;color:#333;background:#fff;font-family:"Microsoft YaHei","simsun","Helvetica Neue", Arial, Helvetica, sans-serif;} +img{border:0;vertical-align:bottom;} +::-webkit-input-placeholder{color:#999;} +:-moz-placeholder{color:#999;} +::-moz-placeholder{color:#999;} +:-ms-input-placeholder{color:#ccc;} +*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} +*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} +button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;} +textarea{overflow:auto;} +input:focus,textarea:focus,button:focus,select:focus{outline:none;} +input::-ms-clear{display:none;} +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;} +audio,canvas,progress,video{display:inline-block;vertical-align:baseline;} +audio:not([controls]){display:none;height:0;} +[hidden],template{display:none;} +a{background:transparent;} +a:active,a:hover{outline:0;} +a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} +abbr[title]{border-bottom:1px dotted;} +b,strong{font-weight:bold;} +dfn{font-style:italic;} +mark{color:#000;background:#ff0;} +small{font-size:80%;} +sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;} +sup{top:-.5em;} +sub{bottom:-.25em;} +svg:not(:root){overflow:hidden;} +figure{margin:1em 40px;} +hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box;} +pre{overflow:auto;} +code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em;} +button,input,optgroup,select,textarea{margin:0;font:inherit;} +button{overflow:visible;} +button,select{text-transform:none;} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;} +button[disabled],html input[disabled]{cursor:default;} +button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;} +input{line-height:normal;} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;} +input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto;} +input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;} +input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} +fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0;} +legend{padding:0;border:0;} +optgroup{font-weight:bold;} +table{border-spacing:0;border-collapse:collapse;} +td,th{padding:0;} +.button{border:solid 1px #ddd;background:transparent;border-radius:4px;font-size:14px;padding:6px 15px;margin:0;display:inline-block;line-height:20px;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.button[disabled]{pointer-events:none;cursor:not-allowed;webkit-box-shadow:none;box-shadow:none;filter:alpha(opacity=50);opacity:.5;} +.button:active{background-image:none;outline:0;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.button:hover{transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.button-block{display:block;width:100%;} +.button-large{padding:15px 20px;font-size:24px;line-height:24px;} +.button-big{padding:10px 15px;font-size:18px;line-height:22px;} +.button-small{padding:5px 10px;font-size:12px;font-weight:normal;line-height:18px;} +.button-little{padding:3px 5px;font-size:12px;font-weight:normal;line-height:16px;} +.button.bg-main,.button.bg-sub,.button.bg-dot,.button.bg-black,.button.bg-gray,.button.bg-red,.button.bg-yellow,.button.bg-blue,.button.bg-green{color:#fff;} +.layout{width:100%;} +.container,.container-layout{margin:0 auto;padding:0 10px;} +@media (min-width:760px){.container{width:760px;}} +@media (min-width:1000px){.container{width:1000px;}} +@media (min-width:1200px){.container{width:1200px;}} +.line{margin:0;padding:0;} +.x1,.x2,.x3,.x4,.x5,.x6,.x7,.x8,.x9,.x10,.x11,.x12,.xl1,.xl2,.xl3,.xl4,.xl5,.xl6,.xl7,.xl8,.xl9,.xl10,.xl11,.xl12,.xs1,.xs2,.xs3,.xs4,.xs5,.xs6,.xs7,.xs8,.xs9,.xs10,.xs11,.xs12,.xm1,.xm2,.xm3,.xm4,.xm5,.xm6,.xm7,.xm8,.xm9,.xm10,.xm11,.xm12,.xb1,.xb2,.xb3,.xb4,.xb5,.xb6,.xb7,.xb8,.xb9,.xb10,.xb11,.xb12{position:relative;min-height:1px;} +.line-big{margin-left:-10px;margin-right:-10px;} +.line-big .x1,.line-big .x2,.line-big .x3,.line-big .x4,.line-big .x5,.line-big .x6,.line-big .x7,.line-big .x8,.line-big .x9,.line-big .x10,.line-big .x11,.line-big .x12, +.line-big .xl1,.line-big .xl2,.line-big .xl3,.line-big .xl4,.line-big .xl5,.line-big .xl6,.line-big .xl7,.line-big .xl8,.line-big .xl9,.line-big .xl10,.line-big .xl11,.line-big .xl12, +.line-big .xs1,.line-big .xs2,.line-big .xs3,.line-big .xs4,.line-big .xs5,.line-big .xs6,.line-big .xs7,.line-big .xs8,.line-big .xs9,.line-big .xs10,.line-big .xs11,.line-big .xs12, +.line-big .xm1,.line-big .xm2,.line-big .xm3,.line-big .xm4,.line-big .xm5,.line-big .xm6,.line-big .xm7,.line-big .xm8,.line-big .xm9,.line-big .xm10,.line-big .xm11,.line-big .xm12, +.line-big .xb1,.line-big .xb2,.line-big .xb3,.line-big .xb4,.line-big .xb5,.line-big .xb6,.line-big .xb7,.line-big .xb8,.line-big .xb9,.line-big .xb10,.line-big .xb11,.line-big .xb12{position:relative;min-height:1px;padding-right:10px;padding-left:10px;} +.line-middle{margin-left:-5px;margin-right:-5px;} +.line-middle .x1,.line-middle .x2,.line-middle .x3,.line-middle .x4,.line-middle .x5,.line-middle .x6,.line-middle .x7,.line-middle .x8,.line-middle .x9,.line-middle .x10,.line-middle .x11,.line-middle .x12, +.line-middle .xl1,.line-middle .xl2,.line-middle .xl3,.line-middle .xl4,.line-middle .xl5,.line-middle .xl6,.line-middle .xl7,.line-middle .xl8,.line-middle .xl9,.line-middle .xl10,.line-middle .xl11,.line-middle .xl12, +.line-middle .xs1,.line-middle .xs2,.line-middle .xs3,.line-middle .xs4,.line-middle .xs5,.line-middle .xs6,.line-middle .xs7,.line-middle .xs8,.line-middle .xs9,.line-middle .xs10,.line-middle .xs11,.line-middle .xs12, +.line-middle .xm1,.line-middle .xm2,.line-middle .xm3,.line-middle .xm4,.line-middle .xm5,.line-middle .xm6,.line-middle .xm7,.line-middle .xm8,.line-middle .xm9,.line-middle .xm10,.line-middle .xm11,.line-middle .xm12, +.line-middle .xb1,.line-middle .xb2,.line-middle .xb3,.line-middle .xb4,.line-middle .xb5,.line-middle .xb6,.line-middle .xb7,.line-middle .xb8,.line-middle .xb9,.line-middle .xb10,.line-middle .xb11,.line-middle .xb12{position:relative;min-height:1px;padding-right:5px;padding-left:5px;} +.line-small{margin-left:-2px;margin-right:-2px;} +.line-small .x1,.line-small .x2,.line-small .x3,.line-small .x4,.line-small .x5,.line-small .x6,.line-small .x7,.line-small .x8,.line-small .x9,.line-small .x10,.line-small .x11,.line-small .x12, +.line-small .xl1,.line-small .xl2,.line-small .xl3,.line-small .xl4,.line-small .xl5,.line-small .xl6,.line-small .xl7,.line-small .xl8,.line-small .xl9,.line-small .xl10,.line-small .xl11,.line-small .xl12, +.line-small .xs1,.line-small .xs2,.line-small .xs3,.line-small .xs4,.line-small .xs5,.line-small .xs6,.line-small .xs7,.line-small .xs8,.line-small .xs9,.line-small .xs10,.line-small .xs11,.line-small .xs12, +.line-small .xm1,.line-small .xm2,.line-small .xm3,.line-small .xm4,.line-small .xm5,.line-small .xm6,.line-small .xm7,.line-small .xm8,.line-small .xm9,.line-small .xm10,.line-small .xm11,.line-small .xm12, +.line-small .xb1,.line-small .xb2,.line-small .xb3,.line-small .xb4,.line-small .xb5,.line-small .xb6,.line-small .xb7,.line-small .xb8,.line-small .xb9,.line-small .xb10,.line-small .xb11,.line-small .xb12{position:relative;min-height:1px;padding-right:2px;padding-left:2px;} +.x1,.x2,.x3,.x4,.x5,.x6,.x7,.x8,.x9,.x10,.x11,.x12{float:left;} +.x1{width:8.33333333%;}.x2{width:16.66666667%;}.x3{width:25%;}.x4{width:33.33333333%;}.x5{width:41.66666667%;}.x6{width:50%;}.x7{width:58.33333333%;}.x8{width:66.66666667%;}.x9{width:75%;}.x10{width:83.33333333%;}.x11{width:91.66666667%;}.x12{width:100%;} +.x0-left{left:0;}.x1-left{left:8.33333333%;}.x2-left{left:16.66666667%;}.x3-left{left:25%;}.x4-left{left:33.33333333%;}.x5-left{left:41.66666667%;}.x6-left{left:50%;}.x7-left{left:58.33333333%;}.x8-left{left:66.66666667%;}.x9-left{left:75%;}.x10-left{left:83.33333333%;}.x11-left{left:91.66666667%;}.x12-left{left:100%;} +.x0-right{right:0;}.x1-right{right:8.33333333%;}.x2-right{right:16.66666667%;}.x3-right{right:25%;}.x4-right{right:33.33333333%;}.x5-right{right:41.66666667%;}.x6-right{right:50%;}.x7-right{right:58.33333333%;}.x8-right{right:66.66666667%;}.x9-right{right:75%;}.x10-right{right:83.33333333%;}.x11-right{right:91.66666667%;}.x12-right{right:100%;} +.x0-move{margin-left:0;}.x1-move{margin-left:8.33333333%;}.x2-move{margin-left:16.66666667%;}.x3-move{margin-left:25%;}.x4-move{margin-left:33.33333333%;}.x5-move{margin-left:41.66666667%;}.x6-move{margin-left:50%;}.x7-move{margin-left:58.33333333%;}.x8-move{margin-left:66.66666667%;}.x9-move{margin-left:75%;}.x10-move{margin-left:83.33333333%;}.x11-move{margin-left:91.66666667%;}.x12-move{margin-left:100%;} +@media (min-width:300px){ +.xl1,.xl2,.xl3,.xl4,.xl5,.xl6,.xl7,.xl8,.xl9,.xl10,.xl11,.xl12{float:left;} +.xl1{width:8.33333333%;}.xl2{width:16.66666667%;}.xl3{width:25%;}.xl4{width:33.33333333%;}.xl5{width:41.66666667%;}.xl6{width:50%;}.xl7{width:58.33333333%;}.xl8{width:66.66666667%;}.xl9{width:75%;}.xl10{width:83.33333333%;}.xl11{width:91.66666667%;}.xl12{width:100%;} +.xl0-left{left:0;}.xl1-left{left:8.33333333%;}.xl2-left{left:16.66666667%;}.xl3-left{left:25%;}.xl4-left{left:33.33333333%;}.xl5-left{left:41.66666667%;}.xl6-left{left:50%;}.xl7-left{left:58.33333333%;}.xl8-left{left:66.66666667%;}.xl9-left{left:75%;}.xl10-left{left:83.33333333%;}.xl11-left{left:91.66666667%;}.xl12-left{left:100%;} +.xl0-right{right:0;}.xl1-right{right:8.33333333%;}.xl2-right{right:16.66666667%;}.xl3-right{right:25%;}.xl4-right{right:33.33333333%;}.xl5-right{right:41.66666667%;}.xl6-right{right:50%;}.xl7-right{right:58.33333333%;}.xl8-right{right:66.66666667%;}.xl9-right{right:75%;}.xl10-right{right:83.33333333%;}.xl11-right{right:91.66666667%;}.xl12-right{right:100%;} +.xl0-move{margin-left:0;}.xl1-move{margin-left:8.33333333%;}.xl2-move{margin-left:16.66666667%;}.xl3-move{margin-left:25%;}.xl4-move{margin-left:33.33333333%;}.xl5-move{margin-left:41.66666667%;}.xl6-move{margin-left:50%;}.xl7-move{margin-left:58.33333333%;}.xl8-move{margin-left:66.66666667%;}.xl9-move{margin-left:75%;}.xl10-move{margin-left:83.33333333%;}.xl11-move{margin-left:91.66666667%;}.xl12-move{margin-left:100%;} +} +@media (min-width:760px){ +.xs1,.xs2,.xs3,.xs4,.xs5,.xs6,.xs7,.xs8,.xs9,.xs10,.xs11,.xs12{float:left;} +.xs1{width:8.33333333%;}.xs2{width:16.66666667%;}.xs3{width:25%;}.xs4{width:33.33333333%;}.xs5{width:41.66666667%;}.xs6{width:50%;}.xs7{width:58.33333333%;}.xs8{width:66.66666667%;}.xs9{width:75%;}.xs10{width:83.33333333%;}.xs11{width:91.66666667%;}.xs12{width:100%;} +.xs0-left{left:0;}.xs1-left{left:8.33333333%;}.xs2-left{left:16.66666667%;}.xs3-left{left:25%;}.xs4-left{left:33.33333333%;}.xs5-left{left:41.66666667%;}.xs6-left{left:50%;}.xs7-left{left:58.33333333%;}.xs8-left{left:66.66666667%;}.xs9-left{left:75%;}.xs10-left{left:83.33333333%;}.xs11-left{left:91.66666667%;}.xs12-left{left:100%;} +.xs0-right{right:0;}.xs1-right{right:8.33333333%;}.xs2-right{right:16.66666667%;}.xs3-right{right:25%;}.xs4-right{right:33.33333333%;}.xs5-right{right:41.66666667%;}.xs6-right{right:50%;}.xs7-right{right:58.33333333%;}.xs8-right{right:66.66666667%;}.xs9-right{right:75%;}.xs10-right{right:83.33333333%;}.xs11-right{right:91.66666667%;}.xs12-right{right:100%;} +.xs0-move{margin-left:0;}.xs1-move{margin-left:8.33333333%;}.xs2-move{margin-left:16.66666667%;}.xs3-move{margin-left:25%;}.xs4-move{margin-left:33.33333333%;}.xs5-move{margin-left:41.66666667%;}.xs6-move{margin-left:50%;}.xs7-move{margin-left:58.33333333%;}.xs8-move{margin-left:66.66666667%;}.xs9-move{margin-left:75%;}.xs10-move{margin-left:83.33333333%;}.xs11-move{margin-left:91.66666667%;}.xs12-move{margin-left:100%;} +} +@media (min-width:1000px){ +.xm1,.xm2,.xm3,.xm4,.xm5,.xm6,.xm7,.xm8,.xm9,.xm10,.xm11,.xm12{float:left;} +.xm1{width:8.33333333%;}.xm2{width:16.66666667%;}.xm3{width:25%;}.xm4{width:33.33333333%;}.xm5{width:41.66666667%;}.xm6{width:50%;}.xm7{width:58.33333333%;}.xm8{width:66.66666667%;}.xm9{width:75%;}.xm10{width:83.33333333%;}.xm11{width:91.66666667%;}.xm12{width:100%;} +.xm0-left{left:0;}.xm1-left{left:8.33333333%;}.xm2-left{left:16.66666667%;}.xm3-left{left:25%;}.xm4-left{left:33.33333333%;}.xm5-left{left:41.66666667%;}.xm6-left{left:50%;}.xm7-left{left:58.33333333%;}.xm8-left{left:66.66666667%;}.xm9-left{left:75%;}.xm10-left{left:83.33333333%;}.xm11-left{left:91.66666667%;}.xm12-left{left:100%;} +.xm0-right{right:0;}.xm1-right{right:8.33333333%;}.xm2-right{right:16.66666667%;}.xm3-right{right:25%;}.xm4-right{right:33.33333333%;}.xm5-right{right:41.66666667%;}.xm6-right{right:50%;}.xm7-right{right:58.33333333%;}.xm8-right{right:66.66666667%;}.xm9-right{right:75%;}.xm10-right{right:83.33333333%;}.xm11-right{right:91.66666667%;}.xm12-right{right:100%;} +.xm0-move{margin-left:0;}.xm1-move{margin-left:8.33333333%;}.xm2-move{margin-left:16.66666667%;}.xm3-move{margin-left:25%;}.xm4-move{margin-left:33.33333333%;}.xm5-move{margin-left:41.66666667%;}.xm6-move{margin-left:50%;}.xm7-move{margin-left:58.33333333%;}.xm8-move{margin-left:66.66666667%;}.xm9-move{margin-left:75%;}.xm10-move{margin-left:83.33333333%;}.xm11-move{margin-left:91.66666667%;}.xm12-move{margin-left:100%;} +} +@media (min-width:1200px){ +.xb1,.xb2,.xb3,.xb4,.xb5,.xb6,.xb7,.xb8,.xb9,.xb10,.xb11,.xb12{float:left;} +.xb1{width:8.33333333%;}.xb2{width:16.66666667%;}.xb3{width:25%;}.xb4{width:33.33333333%;}.xb5{width:41.66666667%;}.xb6{width:50%;}.xb7{width:58.33333333%;}.xb8{width:66.66666667%;}.xb9{width:75%;}.xb10{width:83.33333333%;}.xb11{width:91.66666667%;}.xb12{width:100%;} +.xb0-left{left:0;}.xb1-left{left:8.33333333%;}.xb2-left{left:16.66666667%;}.xb3-left{left:25%;}.xb4-left{left:33.33333333%;}.xb5-left{left:41.66666667%;}.xb6-left{left:50%;}.xb7-left{left:58.33333333%;}.xb8-left{left:66.66666667%;}.xb9-left{left:75%;}.xb10-left{left:83.33333333%;}.xb11-left{left:91.66666667%;}.xb12-left{left:100%;} +.xb0-right{right:0;}.xb1-right{right:8.33333333%;}.xb2-right{right:16.66666667%;}.xb3-right{right:25%;}.xb4-right{right:33.33333333%;}.xb5-right{right:41.66666667%;}.xb6-right{right:50%;}.xb7-right{right:58.33333333%;}.xb8-right{right:66.66666667%;}.xb9-right{right:75%;}.xb10-right{right:83.33333333%;}.xb11-right{right:91.66666667%;}.xb12-right{right:100%;} +.xb0-move{margin-left:0;}.xb1-move{margin-left:8.33333333%;}.xb2-move{margin-left:16.66666667%;}.xb3-move{margin-left:25%;}.xb4-move{margin-left:33.33333333%;}.xb5-move{margin-left:41.66666667%;}.xb6-move{margin-left:50%;}.xb7-move{margin-left:58.33333333%;}.xb8-move{margin-left:66.66666667%;}.xb9-move{margin-left:75%;}.xb10-move{margin-left:83.33333333%;}.xb11-move{margin-left:91.66666667%;}.xb12-move{margin-left:100%;} +} +@media (max-width:760px){ +.show-l{display:block !important;} +.hidden-l{display:none !important;} +} +@media (min-width:761px) and (max-width:1000px){ +.show-s{display:block !important;} +.hidden-s{display:none !important;} +} +@media (min-width:1001px) and (max-width:1200px){ +.show-m{display:block !important;} +.hidden-m{display:none !important;} +} +@media (min-width:1201px){ +.show-b{display:block !important;} +.hidden-b{display:none !important;} +} + +@font-face{ +font-family:'FontAwesome'; +src:url('http://libs.baidu.com/fontawesome/4.1.0/fonts/fontawesome-webfont.eot?v=4.1.0'); +src:url('http://libs.baidu.com/fontawesome/4.1.0/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'), url('http://libs.baidu.com/fontawesome/4.1.0/fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'), url('http://libs.baidu.com/fontawesome/4.1.0/fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'), url('http://libs.baidu.com/fontawesome/4.1.0/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg'); +font-weight:normal;font-style:normal; +} + + +[class*='icon-']:before{display:inline-block;font-family:"FontAwesome";font-weight:normal;font-style:normal;vertical-align:baseline;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;} +.icon-glass:before{content:"\f000";}.icon-music:before{content:"\f001";}.icon-search:before{content:"\f002";}.icon-envelope-o:before{content:"\f003";}.icon-heart:before{content:"\f004";}.icon-star:before{content:"\f005";}.icon-star-o:before{content:"\f006";}.icon-user:before{content:"\f007";}.icon-film:before{content:"\f008";}.icon-th-large:before{content:"\f009";}.icon-th:before{content:"\f00a";}.icon-th-list:before{content:"\f00b";}.icon-check:before{content:"\f00c";}.icon-times:before{content:"\f00d";}.icon-search-plus:before{content:"\f00e";} +.icon-search-minus:before{content:"\f010";}.icon-power-off:before{content:"\f011";}.icon-signal:before{content:"\f012";}.icon-gear:before,.icon-cog:before{content:"\f013";}.icon-trash-o:before{content:"\f014";}.icon-home:before{content:"\f015";}.icon-file-o:before{content:"\f016";}.icon-clock-o:before{content:"\f017";}.icon-road:before{content:"\f018";}.icon-download:before{content:"\f019";}.icon-arrow-circle-o-down:before{content:"\f01a";}.icon-arrow-circle-o-up:before{content:"\f01b";}.icon-inbox:before{content:"\f01c";}.icon-play-circle-o:before{content:"\f01d";}.icon-rotate-right:before,.icon-repeat:before{content:"\f01e";} +.icon-refresh:before{content:"\f021";}.icon-list-alt:before{content:"\f022";}.icon-lock:before{content:"\f023";}.icon-flag:before{content:"\f024";}.icon-headphones:before{content:"\f025";}.icon-volume-off:before{content:"\f026";}.icon-volume-down:before{content:"\f027";}.icon-volume-up:before{content:"\f028";}.icon-qrcode:before{content:"\f029";}.icon-barcode:before{content:"\f02a";}.icon-tag:before{content:"\f02b";}.icon-tags:before{content:"\f02c";}.icon-book:before{content:"\f02d";}.icon-bookmark:before{content:"\f02e";}.icon-print:before{content:"\f02f";} +.icon-camera:before{content:"\f030";}.icon-font:before{content:"\f031";}.icon-bold:before{content:"\f032";}.icon-italic:before{content:"\f033";}.icon-text-height:before{content:"\f034";}.icon-text-width:before{content:"\f035";}.icon-align-left:before{content:"\f036";}.icon-align-center:before{content:"\f037";}.icon-align-right:before{content:"\f038";}.icon-align-justify:before{content:"\f039";}.icon-list:before{content:"\f03a";}.icon-dedent:before,.icon-outdent:before{content:"\f03b";}.icon-indent:before{content:"\f03c";}.icon-video-camera:before{content:"\f03d";}.icon-photo:before,.icon-image:before,.icon-picture-o:before{content:"\f03e";} +.icon-pencil:before{content:"\f040";}.icon-map-marker:before{content:"\f041";}.icon-adjust:before{content:"\f042";}.icon-tint:before{content:"\f043";}.icon-edit:before,.icon-pencil-square-o:before{content:"\f044";}.icon-share-square-o:before{content:"\f045";}.icon-check-square-o:before{content:"\f046";}.icon-arrows:before{content:"\f047";}.icon-step-backward:before{content:"\f048";}.icon-fast-backward:before{content:"\f049";}.icon-backward:before{content:"\f04a";}.icon-play:before{content:"\f04b";}.icon-pause:before{content:"\f04c";}.icon-stop:before{content:"\f04d";}.icon-forward:before{content:"\f04e";} +.icon-fast-forward:before{content:"\f050";}.icon-step-forward:before{content:"\f051";}.icon-eject:before{content:"\f052";}.icon-chevron-left:before{content:"\f053";}.icon-chevron-right:before{content:"\f054";}.icon-plus-circle:before{content:"\f055";}.icon-minus-circle:before{content:"\f056";}.icon-times-circle:before{content:"\f057";}.icon-check-circle:before{content:"\f058";}.icon-question-circle:before{content:"\f059";}.icon-info-circle:before{content:"\f05a";}.icon-crosshairs:before{content:"\f05b";}.icon-times-circle-o:before{content:"\f05c";}.icon-check-circle-o:before{content:"\f05d";}.icon-ban:before{content:"\f05e";} +.icon-arrow-left:before{content:"\f060";}.icon-arrow-right:before{content:"\f061";}.icon-arrow-up:before{content:"\f062";}.icon-arrow-down:before{content:"\f063";}.icon-mail-forward:before,.icon-share:before{content:"\f064";}.icon-expand:before{content:"\f065";}.icon-compress:before{content:"\f066";}.icon-plus:before{content:"\f067";}.icon-minus:before{content:"\f068";}.icon-asterisk:before{content:"\f069";}.icon-exclamation-circle:before{content:"\f06a";}.icon-gift:before{content:"\f06b";}.icon-leaf:before{content:"\f06c";}.icon-fire:before{content:"\f06d";}.icon-eye:before{content:"\f06e";} +.icon-eye-slash:before{content:"\f070";}.icon-warning:before,.icon-exclamation-triangle:before{content:"\f071";}.icon-plane:before{content:"\f072";}.icon-calendar:before{content:"\f073";}.icon-random:before{content:"\f074";}.icon-comment:before{content:"\f075";}.icon-magnet:before{content:"\f076";}.icon-chevron-up:before{content:"\f077";}.icon-chevron-down:before{content:"\f078";}.icon-retweet:before{content:"\f079";}.icon-shopping-cart:before{content:"\f07a";}.icon-folder:before{content:"\f07b";}.icon-folder-open:before{content:"\f07c";}.icon-arrows-v:before{content:"\f07d";}.icon-arrows-h:before{content:"\f07e";} +.icon-bar-chart-o:before{content:"\f080";}.icon-twitter-square:before{content:"\f081";}.icon-facebook-square:before{content:"\f082";}.icon-camera-retro:before{content:"\f083";}.icon-key:before{content:"\f084";}.icon-gears:before,.icon-cogs:before{content:"\f085";}.icon-comments:before{content:"\f086";}.icon-thumbs-o-up:before{content:"\f087";}.icon-thumbs-o-down:before{content:"\f088";}.icon-star-half:before{content:"\f089";}.icon-heart-o:before{content:"\f08a";}.icon-sign-out:before{content:"\f08b";}.icon-linkedin-square:before{content:"\f08c";}.icon-thumb-tack:before{content:"\f08d";}.icon-external-link:before{content:"\f08e";} +.icon-sign-in:before{content:"\f090";}.icon-trophy:before{content:"\f091";}.icon-github-square:before{content:"\f092";}.icon-upload:before{content:"\f093";}.icon-lemon-o:before{content:"\f094";}.icon-phone:before{content:"\f095";}.icon-square-o:before{content:"\f096";}.icon-bookmark-o:before{content:"\f097";}.icon-phone-square:before{content:"\f098";}.icon-twitter:before{content:"\f099";}.icon-facebook:before{content:"\f09a";}.icon-github:before{content:"\f09b";}.icon-unlock:before{content:"\f09c";}.icon-credit-card:before{content:"\f09d";}.icon-rss:before{content:"\f09e";} +.icon-hdd-o:before{content:"\f0a0";}.icon-bullhorn:before{content:"\f0a1";}.icon-bell:before{content:"\f0f3";}.icon-certificate:before{content:"\f0a3";}.icon-hand-o-right:before{content:"\f0a4";}.icon-hand-o-left:before{content:"\f0a5";}.icon-hand-o-up:before{content:"\f0a6";}.icon-hand-o-down:before{content:"\f0a7";}.icon-arrow-circle-left:before{content:"\f0a8";}.icon-arrow-circle-right:before{content:"\f0a9";}.icon-arrow-circle-up:before{content:"\f0aa";}.icon-arrow-circle-down:before{content:"\f0ab";}.icon-globe:before{content:"\f0ac";}.icon-wrench:before{content:"\f0ad";}.icon-tasks:before{content:"\f0ae";} +.icon-filter:before{content:"\f0b0";}.icon-briefcase:before{content:"\f0b1";}.icon-arrows-alt:before{content:"\f0b2";}.icon-group:before,.icon-users:before{content:"\f0c0";}.icon-chain:before,.icon-link:before{content:"\f0c1";}.icon-cloud:before{content:"\f0c2";}.icon-flask:before{content:"\f0c3";}.icon-cut:before,.icon-scissors:before{content:"\f0c4";}.icon-copy:before,.icon-files-o:before{content:"\f0c5";}.icon-paperclip:before{content:"\f0c6";}.icon-save:before,.icon-floppy-o:before{content:"\f0c7";}.icon-square:before{content:"\f0c8";}.icon-navicon:before,.icon-reorder:before,.icon-bars:before{content:"\f0c9";}.icon-list-ul:before{content:"\f0ca";}.icon-list-ol:before{content:"\f0cb";}.icon-strikethrough:before{content:"\f0cc";}.icon-underline:before{content:"\f0cd";}.icon-table:before{content:"\f0ce";} +.icon-magic:before{content:"\f0d0";}.icon-truck:before{content:"\f0d1";}.icon-pinterest:before{content:"\f0d2";}.icon-pinterest-square:before{content:"\f0d3";}.icon-google-plus-square:before{content:"\f0d4";}.icon-google-plus:before{content:"\f0d5";}.icon-money:before{content:"\f0d6";}.icon-caret-down:before{content:"\f0d7";}.icon-caret-up:before{content:"\f0d8";}.icon-caret-left:before{content:"\f0d9";}.icon-caret-right:before{content:"\f0da";}.icon-columns:before{content:"\f0db";}.icon-unsorted:before,.icon-sort:before{content:"\f0dc";}.icon-sort-down:before,.icon-sort-desc:before{content:"\f0dd";}.icon-sort-up:before,.icon-sort-asc:before{content:"\f0de";} +.icon-envelope:before{content:"\f0e0";}.icon-linkedin:before{content:"\f0e1";}.icon-rotate-left:before,.icon-undo:before{content:"\f0e2";}.icon-legal:before,.icon-gavel:before{content:"\f0e3";}.icon-dashboard:before,.icon-tachometer:before{content:"\f0e4";}.icon-comment-o:before{content:"\f0e5";}.icon-comments-o:before{content:"\f0e6";}.icon-flash:before,.icon-bolt:before{content:"\f0e7";}.icon-sitemap:before{content:"\f0e8";}.icon-umbrella:before{content:"\f0e9";}.icon-paste:before,.icon-clipboard:before{content:"\f0ea";}.icon-lightbulb-o:before{content:"\f0eb";}.icon-exchange:before{content:"\f0ec";}.icon-cloud-download:before{content:"\f0ed";}.icon-cloud-upload:before{content:"\f0ee";} +.icon-user-md:before{content:"\f0f0";}.icon-stethoscope:before{content:"\f0f1";}.icon-suitcase:before{content:"\f0f2";}.icon-bell-o:before{content:"\f0a2";}.icon-coffee:before{content:"\f0f4";}.icon-cutlery:before{content:"\f0f5";}.icon-file-text-o:before{content:"\f0f6";}.icon-building-o:before{content:"\f0f7";}.icon-hospital-o:before{content:"\f0f8";}.icon-ambulance:before{content:"\f0f9";}.icon-medkit:before{content:"\f0fa";}.icon-fighter-jet:before{content:"\f0fb";}.icon-beer:before{content:"\f0fc";}.icon-h-square:before{content:"\f0fd";}.icon-plus-square:before{content:"\f0fe";} +.icon-angle-double-left:before{content:"\f100";}.icon-angle-double-right:before{content:"\f101";}.icon-angle-double-up:before{content:"\f102";}.icon-angle-double-down:before{content:"\f103";}.icon-angle-left:before{content:"\f104";}.icon-angle-right:before{content:"\f105";}.icon-angle-up:before{content:"\f106";}.icon-angle-down:before{content:"\f107";}.icon-desktop:before{content:"\f108";}.icon-laptop:before{content:"\f109";}.icon-tablet:before{content:"\f10a";}.icon-mobile-phone:before,.icon-mobile:before{content:"\f10b";}.icon-circle-o:before{content:"\f10c";}.icon-quote-left:before{content:"\f10d";}.icon-quote-right:before{content:"\f10e";} +.icon-spinner:before{content:"\f110";}.icon-circle:before{content:"\f111";}.icon-mail-reply:before,.icon-reply:before{content:"\f112";}.icon-github-alt:before{content:"\f113";}.icon-folder-o:before{content:"\f114";}.icon-folder-open-o:before{content:"\f115";}.icon-smile-o:before{content:"\f118";}.icon-frown-o:before{content:"\f119";}.icon-meh-o:before{content:"\f11a";}.icon-gamepad:before{content:"\f11b";}.icon-keyboard-o:before{content:"\f11c";}.icon-flag-o:before{content:"\f11d";}.icon-flag-checkered:before{content:"\f11e";} +.icon-terminal:before{content:"\f120";}.icon-code:before{content:"\f121";}.icon-mail-reply-all:before,.icon-reply-all:before{content:"\f122";}.icon-star-half-empty:before,.icon-star-half-full:before,.icon-star-half-o:before{content:"\f123";}.icon-location-arrow:before{content:"\f124";}.icon-crop:before{content:"\f125";}.icon-code-fork:before{content:"\f126";}.icon-unlink:before,.icon-chain-broken:before{content:"\f127";}.icon-question:before{content:"\f128";}.icon-info:before{content:"\f129";}.icon-exclamation:before{content:"\f12a";}.icon-superscript:before{content:"\f12b";}.icon-subscript:before{content:"\f12c";}.icon-eraser:before{content:"\f12d";}.icon-puzzle-piece:before{content:"\f12e";} +.icon-microphone:before{content:"\f130";}.icon-microphone-slash:before{content:"\f131";}.icon-shield:before{content:"\f132";}.icon-calendar-o:before{content:"\f133";}.icon-fire-extinguisher:before{content:"\f134";}.icon-rocket:before{content:"\f135";}.icon-maxcdn:before{content:"\f136";}.icon-chevron-circle-left:before{content:"\f137";}.icon-chevron-circle-right:before{content:"\f138";}.icon-chevron-circle-up:before{content:"\f139";}.icon-chevron-circle-down:before{content:"\f13a";}.icon-html5:before{content:"\f13b";}.icon-css3:before{content:"\f13c";}.icon-anchor:before{content:"\f13d";}.icon-unlock-alt:before{content:"\f13e";} +.icon-bullseye:before{content:"\f140";}.icon-ellipsis-h:before{content:"\f141";}.icon-ellipsis-v:before{content:"\f142";}.icon-rss-square:before{content:"\f143";}.icon-play-circle:before{content:"\f144";}.icon-ticket:before{content:"\f145";}.icon-minus-square:before{content:"\f146";}.icon-minus-square-o:before{content:"\f147";}.icon-level-up:before{content:"\f148";}.icon-level-down:before{content:"\f149";}.icon-check-square:before{content:"\f14a";}.icon-pencil-square:before{content:"\f14b";}.icon-external-link-square:before{content:"\f14c";}.icon-share-square:before{content:"\f14d";}.icon-compass:before{content:"\f14e";} +.icon-toggle-down:before,.icon-caret-square-o-down:before{content:"\f150";}.icon-toggle-up:before,.icon-caret-square-o-up:before{content:"\f151";}.icon-toggle-right:before,.icon-caret-square-o-right:before{content:"\f152";}.icon-euro:before,.icon-eur:before{content:"\f153";}.icon-gbp:before{content:"\f154";}.icon-dollar:before,.icon-usd:before{content:"\f155";}.icon-rupee:before,.icon-inr:before{content:"\f156";}.icon-cny:before,.icon-rmb:before,.icon-yen:before,.icon-jpy:before{content:"\f157";}.icon-ruble:before,.icon-rouble:before,.icon-rub:before{content:"\f158";}.icon-won:before,.icon-krw:before{content:"\f159";}.icon-bitcoin:before,.icon-btc:before{content:"\f15a";}.icon-file:before{content:"\f15b";}.icon-file-text:before{content:"\f15c";}.icon-sort-alpha-asc:before{content:"\f15d";}.icon-sort-alpha-desc:before{content:"\f15e";} +.icon-sort-amount-asc:before{content:"\f160";}.icon-sort-amount-desc:before{content:"\f161";}.icon-sort-numeric-asc:before{content:"\f162";}.icon-sort-numeric-desc:before{content:"\f163";}.icon-thumbs-up:before{content:"\f164";}.icon-thumbs-down:before{content:"\f165";}.icon-youtube-square:before{content:"\f166";}.icon-youtube:before{content:"\f167";}.icon-xing:before{content:"\f168";}.icon-xing-square:before{content:"\f169";}.icon-youtube-play:before{content:"\f16a";}.icon-dropbox:before{content:"\f16b";}.icon-stack-overflow:before{content:"\f16c";}.icon-instagram:before{content:"\f16d";}.icon-flickr:before{content:"\f16e";} +.icon-adn:before{content:"\f170";}.icon-bitbucket:before{content:"\f171";}.icon-bitbucket-square:before{content:"\f172";}.icon-tumblr:before{content:"\f173";}.icon-tumblr-square:before{content:"\f174";}.icon-long-arrow-down:before{content:"\f175";}.icon-long-arrow-up:before{content:"\f176";}.icon-long-arrow-left:before{content:"\f177";}.icon-long-arrow-right:before{content:"\f178";}.icon-apple:before{content:"\f179";}.icon-windows:before{content:"\f17a";}.icon-android:before{content:"\f17b";}.icon-linux:before{content:"\f17c";}.icon-dribbble:before{content:"\f17d";}.icon-skype:before{content:"\f17e";} +.icon-foursquare:before{content:"\f180";}.icon-trello:before{content:"\f181";}.icon-female:before{content:"\f182";}.icon-male:before{content:"\f183";}.icon-gittip:before{content:"\f184";}.icon-sun-o:before{content:"\f185";}.icon-moon-o:before{content:"\f186";}.icon-archive:before{content:"\f187";}.icon-bug:before{content:"\f188";}.icon-vk:before{content:"\f189";}.icon-weibo:before{content:"\f18a";}.icon-renren:before{content:"\f18b";}.icon-pagelines:before{content:"\f18c";}.icon-stack-exchange:before{content:"\f18d";}.icon-arrow-circle-o-right:before{content:"\f18e";} +.icon-arrow-circle-o-left:before{content:"\f190";}.icon-toggle-left:before,.icon-caret-square-o-left:before{content:"\f191";}.icon-dot-circle-o:before{content:"\f192";}.icon-wheelchair:before{content:"\f193";}.icon-vimeo-square:before{content:"\f194";}.icon-turkish-lira:before,.icon-try:before{content:"\f195";}.icon-plus-square-o:before{content:"\f196";}.icon-space-shuttle:before{content:"\f197";}.icon-slack:before{content:"\f198";}.icon-envelope-square:before{content:"\f199";}.icon-wordpress:before{content:"\f19a";}.icon-openid:before{content:"\f19b";}.icon-institution:before,.icon-bank:before,.icon-university:before{content:"\f19c";}.icon-mortar-board:before,.icon-graduation-cap:before{content:"\f19d";}.icon-yahoo:before{content:"\f19e";} +.icon-google:before{content:"\f1a0";}.icon-reddit:before{content:"\f1a1";}.icon-reddit-square:before{content:"\f1a2";}.icon-stumbleupon-circle:before{content:"\f1a3";}.icon-stumbleupon:before{content:"\f1a4";}.icon-delicious:before{content:"\f1a5";}.icon-digg:before{content:"\f1a6";}.icon-pied-piper-square:before,.icon-pied-piper:before{content:"\f1a7";}.icon-pied-piper-alt:before{content:"\f1a8";}.icon-drupal:before{content:"\f1a9";}.icon-joomla:before{content:"\f1aa";}.icon-language:before{content:"\f1ab";}.icon-fax:before{content:"\f1ac";}.icon-building:before{content:"\f1ad";}.icon-child:before{content:"\f1ae";} +.icon-paw:before{content:"\f1b0";}.icon-spoon:before{content:"\f1b1";}.icon-cube:before{content:"\f1b2";}.icon-cubes:before{content:"\f1b3";}.icon-behance:before{content:"\f1b4";}.icon-behance-square:before{content:"\f1b5";}.icon-steam:before{content:"\f1b6";}.icon-steam-square:before{content:"\f1b7";}.icon-recycle:before{content:"\f1b8";}.icon-automobile:before,.icon-car:before{content:"\f1b9";}.icon-cab:before,.icon-taxi:before{content:"\f1ba";}.icon-tree:before{content:"\f1bb";}.icon-spotify:before{content:"\f1bc";}.icon-deviantart:before{content:"\f1bd";}.icon-soundcloud:before{content:"\f1be";} +.icon-database:before{content:"\f1c0";}.icon-file-pdf-o:before{content:"\f1c1";}.icon-file-word-o:before{content:"\f1c2";}.icon-file-excel-o:before{content:"\f1c3";}.icon-file-powerpoint-o:before{content:"\f1c4";}.icon-file-photo-o:before,.icon-file-picture-o:before,.icon-file-image-o:before{content:"\f1c5";}.icon-file-zip-o:before,.icon-file-archive-o:before{content:"\f1c6";}.icon-file-sound-o:before,.icon-file-audio-o:before{content:"\f1c7";}.icon-file-movie-o:before,.icon-file-video-o:before{content:"\f1c8";}.icon-file-code-o:before{content:"\f1c9";}.icon-vine:before{content:"\f1ca";}.icon-codepen:before{content:"\f1cb";}.icon-jsfiddle:before{content:"\f1cc";}.icon-life-bouy:before,.icon-life-saver:before,.icon-support:before,.icon-life-ring:before{content:"\f1cd";}.icon-circle-o-notch:before{content:"\f1ce";} +.icon-ra:before,.icon-rebel:before{content:"\f1d0";}.icon-ge:before,.icon-empire:before{content:"\f1d1";}.icon-git-square:before{content:"\f1d2";}.icon-git:before{content:"\f1d3";}.icon-hacker-news:before{content:"\f1d4";}.icon-tencent-weibo:before{content:"\f1d5";}.icon-qq:before{content:"\f1d6";}.icon-wechat:before,.icon-weixin:before{content:"\f1d7";}.icon-send:before,.icon-paper-plane:before{content:"\f1d8";}.icon-send-o:before,.icon-paper-plane-o:before{content:"\f1d9";}.icon-history:before{content:"\f1da";}.icon-circle-thin:before{content:"\f1db";}.icon-header:before{content:"\f1dc";}.icon-paragraph:before{content:"\f1dd";}.icon-sliders:before{content:"\f1de";}.icon-share-alt:before{content:"\f1e0";}.icon-share-alt-square:before{content:"\f1e1";}.icon-bomb:before{content:"\f1e2";} +.close{display:inline-block;font-size:24px;cursor:pointer;line-height:24px;} +.close:before{content:"\00d7";} +.leftward{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-right:4px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;} +.rightward{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-left:4px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;} +.upward{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-bottom:4px solid;border-right:4px solid transparent;border-left:4px solid transparent;} +.downward,.arrow{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent;} +.tag{font-size:75%;border-radius:0.25em;background:#999;padding:0.1em 0.5em 0.2em;color:#fff;} +.tag.bg-back,.tag.bg-mix,.tag.bg-white,.tag.bg-red-light,.tag.bg-yellow-light,.tag.bg-blue-light,.tag.bg-green-light{color:inherit;} +.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:2em;} +.badge:empty{display:none} +.badge.bg-back,.badge.bg-mix{color:inherit;} +.badge.bg-white,.badge.bg-red-light,.badge.bg-yellow-light,.badge.bg-blue-light,.badge.bg-green-light{color:#333;} +.badge-corner{position:relative;} +.badge-corner .badge{position:absolute;right:-10px;top:-9px;font-weight:normal;cursor:pointer;} +.progress{height:14px;overflow:hidden;background-color:#f5f5f5;border-radius:7px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);} +.progress-bar{color:#fff;float:left;background-color:#0a0;display:inline-block;font-size:12px;line-height:14px;text-align:center;} +.progress-bar:after{content:"\3000";} +.progress .progress-bar:last-child{border-radius:0 7px 7px 0;} +.progress-big{height:26px;border-radius:13px;} +.progress-big .progress-bar{font-size:14px;line-height:26px;} +.progress-big .progress-bar:last-child{border-radius:0 13px 13px 0;} +.progress-small{height:6px;border-radius:3px;} +.progress-small .progress-bar{font-size:6px;line-height:6px;} +.progress-small .progress-bar:last-child{border-radius:0 3px 3px 0;} +.progress-bar.bg-back,.progress-bar.bg-mix,.progress-bar.bg-white{color:inherit;} +@-webkit-keyframes progress-bar-active{from{background-position:30px 0;}to{background-position:0 0;}} +@keyframes progress-bar-active{from{background-position:30px 0;}to{background-position:0 0;}} +.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, .25) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .25) 50%, rgba(255, 255, 255, .25) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, .25) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .25) 50%, rgba(255, 255, 255, .25) 75%, transparent 75%, transparent);background-size:30px 30px;} +.progress.active .progress-bar{-webkit-animation:progress-bar-active 2s linear infinite normal;animation:progress-bar-active 2s linear infinite normal;} +.range{position:raelative;height:10px;background-color:#f5f5f5;border-radius:5px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);} +.range-scroll{position:aabsolute;width:16px;height:16px;margin-top:-3px;border-radius:8px;cursor:pointer;-webkit-box-shadow:1px 1px 1px rgba(0, 0, 0, .175);box-shadow:1px 1px 1px rgba(0, 0, 0, .175);} +.range-bar{position:absaolute;height:10px;float:left;display:inline-block;border-radius:5px;} +.range-bar span{position:relative;} +.range-scroll-left{float:left;margin-left:-8px;} +.range-scroll-right{float:right;margin-right:-8px;} +.range-group{display:table;} +.range-group .range-area,.range-group input{display:table-cell;} +.range-group .range-area{width:100%;} +.range-group input{width:1%;} +.drop{position:relative;} +.drop-menu{position:absolute;display:none;top:100%;left:0;z-index:1;float:left;min-width:160px;padding:5px 0;margin:1px 0 0;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, .15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175);box-shadow:0 6px 12px rgba(0, 0, 0, .175);} +.drop-menu.pull-right{right:0;left:auto;} +.drop-menu a{color:#333;padding:5px 20px;display:block;clear:both;white-space:nowrap;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.drop-menu a:hover,.drop-menu a:focus{background:#f5f5f5;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.drop-menu .disabled a{color:#999;pointer-events:none;} +.drop-menu .disabled a:hover,.drop-menu .disabled a:focus{cursor:not-allowed;} +.drop-menu .divider{background-color:#ddd;height:1px;overflow:hidden;margin:8px 0;} +.drop-menu .drop-meun-head{display:block;padding:5px 20px;font-size:12px;color:#999;} +.open .drop-menu{display:block;} +.button-group, .button-group-y{display:inline-block;position:relative;vertical-align:middle;} +.button-group .button, .button-group .button-group{float:left;position:relative;font-weight:normal;} +.button-group :not(:first-child):not(:last-child):not(.dropdown-toggle).button,.button-group .button-group .button{border-radius:0;} +.button-group .button, .button-group .button-group .button{margin-left:-1px;} +.button-group :first-child:not(:last-child).button:not(.dropdown-toggle){border-top-right-radius:0px;border-bottom-right-radius:0px;} +.button-group :last-child:not(:first-child).button:not(.dropdown-toggle){border-bottom-left-radius:0px;border-top-left-radius:0px;} +.button-group .button-group:first-child .button:last-child, +.button-group .button-group:first-child .dropdown-toggle{border-top-left-radius:5px;border-bottom-left-radius:5px;} +.button-group .button-group:last-child .button:first-child{border-top-right-radius:5px;border-bottom-right-radius:5px;} +.button-group :not(:first-child).dropdown-toggle{border-bottom-left-radius:0px;border-top-left-radius:0px;padding:6px;} +.button-toolbar{display:inline-block;} +.button-toolbar .button-group{display:inline-block;} +.button-group-y .button, .button-group-y .button-group{float:none;clear:both;display:block;width:100%;font-weight:normal;} +.button-group-y :not(:first-child):not(:last-child):not(.dropdown-toggle).button, +.button-group-y .button-group .button{border-radius:0;} +.button-group-y .button, .button-group-y .button-group-y .button, .button-group-y .button-group .button{margin-left:0;margin-top:-1px;} +.button-group-y :first-child:not(:last-child).button:not(.dropdown-toggle){border-bottom-left-radius:0px;border-bottom-right-radius:0px;} +.button-group-y :last-child:not(:first-child).button:not(.dropdown-toggle){border-top-right-radius:0px;border-top-left-radius:0px;} +.button-group-y .button-group:first-child .button:last-child, +.button-group-y .button-group:first-child .dropdown-toggle{border-top-left-radius:5px;border-top-right-radius:5px;} +.button-group-y .button-group:last-child .button:first-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px;} +.button-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate;text-align:center;} +.button-group-justified > .button,.button-group-justified > .button-group{display:table-cell;float:none;width:1%;} +.button-group-justified > .button-group .button{width:100%;margin:0;} +.button-group-justified .drop-menu{text-align:left;} +.button-group-large .button{padding:15px 20px;font-size:24px;line-height:24px;font-weight:bold;} +.button-group-big .button{padding:10px 15px;font-size:18px;line-height:22px;} +.button-group-small .button{padding:5px 10px;font-size:12px;font-weight:normal;line-height:18px;} +.button-group-little .button{padding:3px 5px;font-size:12px;font-weight:normal;line-height:16px;} +.button-group label input{position:absolute;filter:alpha(opacity=0);opacity:0;z-index:-1;} +.border-red .button.active,.border-yellow .button.active,.border-blue .button.active,.border-green .button.active,.border-main .button.active,.border-sub .button.active,.border-dot .button.active,.border-black .button.active,.border-gray .button.active{color:#fff;} +.dropup .drop-menu{top:auto;bottom:100%;margin-bottom:1px;} +.selected-inline li{position:relative;display:inline-block;width:auto;border:solid 1px #ddd;border-radius:4px;margin-right:5px;padding:3px 9px;cursor:pointer;} +.selected-inline .selected{border:solid 2px #f60;padding:2px 8px;} +.txt{display:inline-block;width:48px;height:48px;line-height:48px;text-align:center;background-color:#f5f5f5;} +.txt-border{display:inline-block;width:48px;height:48px;line-height:48px;border:solid 1px #ddd;padding:3px;vertical-align:bottom;} +.txt-border .txt{display:block;width:100%;height:100%;line-height:40px;} +.txt.bg-main,.txt.bg-sub,.txt.bg-dot,.txt.bg-black,.txt.bg-gray,.txt.bg-red,.txt.bg-yellow,.txt.bg-blue,.txt.bg-green{color:#fff;} +.txt .bg-main,.txt .bg-sub,.txt .bg-dot,.txt .bg-black,.txt .bg-gray,.txt .bg-red,.txt .bg-yellow,.txt .bg-blue,.txt .bg-green{color:#fff;} +.txt span{font-size:12px;} +.txt-border.txt-large{padding:5px;} +.txt-large{width:128px;height:128px;line-height:128px;font-size:36px;} +.txt-large .txt{width:116px;height:116px;line-height:116px;} +.txt-large strong{font-size:80px;font-weight:normal;} +.txt-border.txt-big{padding:4px;} +.txt-big{width:64px;height:64px;line-height:64px;font-size:20px;} +.txt-big .txt{width:54px;height:54px;line-height:54px;} +.txt-big strong{font-size:36px;font-weight:normal;} +.txt-border.txt-small{padding:2px;} +.txt-small{width:32px;height:32px;line-height:32px;} +.txt-small .txt{width:26px;height:26px;line-height:26px;} +.txt-border.txt-little{padding:1px;} +.txt-little{width:16px;height:16px;line-height:16px;font-size:12px;} +.txt-little .txt{width:12px;height:12px;line-height:12px;font-size:12px;} +.media, .media-body{overflow:hidden;zoom:1;} +.media, .media .media{margin-top:15px;} +.media:first-child{margin-top:0;} +.media-body{margin-top:3px;} +.media strong{display:block;} +.media p{margin:5px 0 0 0;text-align:justify;line-height:18px;} +.media.media-y{text-align:center;} +.media.media-x .media-body{margin:0;} +.media.media-x .float-left{margin-right:10px;} +.media.media-x .float-right{margin-left:10px;} +.media.media-x strong{margin-bottom:5px;} +.media-inline .media{display:inline-block;margin-right:15px;margin-top:0;} +.media-inline .media:last-child{margin-right:0;} +.input{font-size:14px;padding:10px;border:solid 1px #ddd; width:100%;line-height:20px;display:block; border-radius:3px; -webkit-appearance:none;} +.label{padding-bottom:7px;display:block;line-height:20px; color:#202020;} +.label label{font-weight:bold;} +.input-file{display:inline-block;position:relative;overflow:hidden;text-align:center;width:auto;color:#333;} +.input-file input[type="file"]{position:absolute;top:0;right:0;font-size:14px;background-color:#fff;transform:translate(-300px, 0px) scale(4);height:40px;opacity:0;filter:alpha(opacity=0);} +.input:focus{border-color:#0ae;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.input-auto{width:auto;display:inline-block;} +input[disabled],input[readonly],textarea[disabled],textarea[readonly],select[disabled],select[readonly]{cursor:not-allowed;background:#eee;}/*IE6无效*/ +textarea.input{height:auto;} +.input-note, .label .float-right{color:#999;font-size:12px;padding-top:2px;line-height:18px;} +.field{position:relative;} +.form-group{padding-bottom:10px;} +.field-icon .input{text-indent:25px;} +.field-icon .icon{position:absolute;left:0;right:auto;width:34px;height:34px;text-align:center;line-height:34px;font-size:16px;font-weight:normal;} +.field-icon-right .icon{position:absolute;right:0;top:0;width:34px;height:34px;text-align:center;line-height:34px;font-size:16px;font-weight:normal;} +.form-x .form-group:after, .form-inline:after{clear:both;content:" ";display:block;height:0;overflow:hidden;visibility:hidden;} +@media (min-width:760px){ +.form-x .form-group .label{float:left;width:15%;text-align:right;padding:7px 7px 7px 0;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;} +.form-x .form-group .field{float:left;width:85%;} +.form-x .form-button{margin-left:15%;} +} +@media (min-width:760px){ +.form-inline{display:inline-block;} +.form-inline .input{width:auto;display:inline-block;} +.form-inline .form-group{display:inline-table;padding-bottom:0;vertical-align:middle;} +.form-inline .form-group .input-group{display:inline-table;width:auto;vertical-align:middle;} +.form-inline .form-group .input-group .input{width:auto;} +.form-inline .form-group .label{display:inline-block;} +.form-inline .form-group .field{display:inline-block;} +.form-inline .form-button{display:inline-block;vertical-align:middle;} +.form-inline .form-button .button{width:auto;} +.form-auto .input{width:auto;display:inline-block;} +.form-auto .input-group{display:inline-table;width:auto;display:inline-block;} +.form-auto .input-group .input{width:auto;display:inline-block;} +.input-inline{padding-left:1px;} +.input-inline input{position:relative;float:left;border-radius:0;margin-left:-1px;width:auto;} +.form-small .input-inline input,.form-big .input-inline input{border-radius:0;} +.input-inline input:first-child{left:1px;border-radius:4px 0 0 4px;} +.input-inline input:last-child{border-radius:0 4px 4px 0;} +} +.input-block{padding-top:8px;} +.input-block:first-child{padding-top:1px;} +.input-block input{position:relative;margin-top:-1px;border-radius:0;} +.form-small .input-block input,.form-big .input-block input{border-radius:0;} +.input-block input:first-child{border-radius:4px 4px 0 0;} +.input-block input:last-child{border-radius:0 0 4px 4px;} +.label-block label{display:block;line-height:24px;} +.input-group{border-collapse:separate;display:table;position:relative;} +.input-group .addon, .input-group .addbtn, .input-group .input{display:table-cell;} +.input-group .addon, .input-group .addbtn{width:1%;white-space:nowrap;vertical-align:middle;} +.input-group .addbtn .button{font-weight:normal;} +.input-group .input{width:100%;} +.input-group .addon{background-color:#f5f5f5;border:1px solid #ddd;border-radius:4px;line-height:1;padding:6px 12px;text-align:center;} +.input-group .addon:first-child, .input-group .addbtn:first-child .button{border-right:0 none;} +.input-group .addon:first-child, .input-group .addbtn:first-child .button, .input-group .input:first-child{border-top-right-radius:0;border-bottom-right-radius:0;} +.input-group .addon:last-child, .input-group .addbtn:last-child .button{border-left:0 none;} +.input-group .addon:last-child, .input-group .addbtn:last-child .button, .input-group .input:last-child{border-top-left-radius:0;border-bottom-left-radius:0;} +.input-group .addon:not(:first-child):not(:last-child),.input-group .addbtn:not(:first-child):not(:last-child) .button,.input-group .input:not(:first-child):not(:last-child){border-radius:0;} +.form-tips .form-group .field{position:relative;zoom:1;} +.form-tips .input-help{position:absolute;z-index:1;float:left;left:0;top:100%;} +.form-tips .input-help ul{border:solid 1px #ddd;background:#fff;padding:10px 10px 10px 25px;box-shadow:0 0 5px #ddd;border-radius:4px;width:160px;min-width:160px;width:auto;_width:160px;} +.input-big, .form-big .input, .form-big .button{padding:10px;font-size:16px;line-height:24px;height:46px;} +.input-small, .form-small .input, .form-small .button{padding:5px;font-size:12px;line-height:18px;height:28px;} +.form-small .addon,.form-small .addbtn{padding:5px 8px;font-size:12px;} +.list-group, .list-link{border:solid 1px #ddd;border-radius:4px;list-style:none;padding:0;} +.list-group li, .list-link a{padding:10px 15px;display:block;border-bottom:solid 1px #ddd;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.list-group li:last-child, .list-link a:last-child{border-bottom:0 none;} +.list-striped li:nth-child(odd){background-color:#f5f5f5;} +.list-link a{color:#333;} +.list-link a:hover{background-color:#f5f5f5;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.list-link a.active:link,.list-link a.active:visited{background-color:#f5f5f5;} +.panel{border:solid 1px #ddd;border-radius:4px;} +.panel-head{background-color:#fcfcfc;padding:10px 15px;border-radius:4px 4px 0 0;border-bottom:solid 1px #ddd;} +.panel-foot{background-color:#f5f5f5;padding:10px 15px;border-radius:0 0 4px 4px;border-top:solid 1px #ddd;} +.panel-body{padding:15px;} +.panel .bg-main,.panel .bg-sub,.panel .bg-dot,.panel .bg-red,.panel .bg-yellow,.panel .bg-green{color:#fff;} +.panel .panel-body + .table, .panel .panel-body + .list-group{border-top:solid 1px #ddd;} +.panel .list-group{border:none;border-radius:0;} +.tab .tab-head strong{float:left;padding:8px 20px 0 0;line-height:20px;} +.tab .tab-more{float:right;margin:10px 0 0 10px;font-size:12px;} +.tab .tab-nav{list-style:none;} +.tab .tab-nav li{display:inline-block;} +.tab .tab-nav li a{color:#333;padding:8px 20px;display:block;border:solid 1px #ddd;line-height:20px;border-bottom:none;border-radius:4px 4px 0 0;} +.tab .tab-nav .active{background-color:#fff;} +.tab .tab-nav .active a{cursor:default;} +.tab .tab-body{border-top:solid 1px #ddd;margin-top:-1px;padding-top:15px;} +.tab .tab-body-bordered{border:solid 1px #ddd;border-radius:4px;padding:15px;} +.tab .tab-body .tab-panel{display:none;} +.tab .tab-body .active{display:block;} +.tab.tab-small strong{padding-top:3px;} +.tab.tab-small .tab-more{margin:5px 0 0 10px;} +.tab.tab-small li a{padding:3px 10px;} +.dialog-mask{position:fixed;left:0;top:0;right:0;bottom:0;background:#000;z-index:10;filter:alpha(opacity=50);opacity:.5;display:block;overflow-x:hidden;overflow-y:auto;} +.dialog{border:1px solid #ddd;box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);border-radius:4px;background-color:#fff;display:none;} +.dialog .dialog-head,.dialog .dialog-foot{padding:10px 20px;} +.dialog .dialog-head{border-bottom:solid 1px #ddd;background-color:#f5f5f5;border-radius:4px 4px 0 0;} +.dialog .dialog-head strong{font-size:16px;} +.dialog .dialog-head .close{float:right;line-height:24px;} +.dialog .dialog-body{padding:15px 20px;} +.dialog .dialog-foot{text-align:right;border-top:solid 1px #ddd;} +.dialog.open{display:block;} +.tip{display:inline-block;background-color:#f5f5f5;border:1px solid #ddd;border-radius:3px;box-shadow:0 2px 5px rgba(0, 0, 0, 0.2);} +.tip p{margin:0px;} +.tip .tip-line{margin:0px;padding:2px 5px;font-size:12px;line-height:16px;} +.tip .tip-title{padding:2px 8px;} +.tip .tip-body{padding:8px;background:#fff;color:#666;border-radius:0 0 3px 3px;font-size:12px;line-height:20px;} +.tip .image{border-radius:3px;} +.tip-bottom.border-red .arrow{border-bottom-color:#f00;} +.tip.bg-main,.tip.bg-sub,.tip.bg-dot,.tip.bg-red,.tip.bg-yellow,.tip.bg-green{color:#fff;} +.alert{border-radius:5px;padding:15px;border:solid 1px #ddd;background-color:#f5f5f5;} +.alert .close{float:right;line-height:18px;} +.radio .icon,.checkbox .icon{display:none;} +.radio .active .icon,.checkbox .active .icon{display:inline-block;} +.collapse .panel{margin-bottom:5px;} +.collapse .panel:last-child{margin-bottom:0;} +.collapse .panel .panel-head{border-bottom-width:0;} +.collapse .panel .panel-body{display:none;} +.collapse .panel.active .panel-head{border-bottom-width:1px;} +.collapse .panel.active .panel-body{display:block;} +.banner{position:relative;width:100%;overflow:hidden;} +.carousel{position:relative;list-style:none;padding:0;} +.carousel .item{display:nones;float:left;position:relative;} +.carousel .active{display:block;} +.carousel img{display:block;max-width:100%;height:auto;} +.banner .pointer{position:absolute;bottom:0;padding:15px;} +.banner .pager-prev, .banner .pager-next{position:absolute;display:none;top:50%;margin-top:-25px;} +.banner .pager-prev{left:20px;} +.banner .pager-next{right:20px;} +.banner:hover .pager-prev,.banner:hover .pager-next{display:block;} +.icon-navicon{display:none;} +@media (max-width:760px){ +.icon-navicon{display:block;} +.nav-navicon, .nav.nav-navicon,.navbar-body.nav-navicon{display:none;} +} +.nav{list-style:none;padding:5px 0 0 0;margin:0;} +.nav li{position:relative;} +.nav a{color:#333;line-height:20px;padding:5px 0;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;display:block;} +.nav a:hover{transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.nav .arrow{display:none;} +.nav .active a{font-weight:bold;} +.nav-head{font-size:14px;font-weight:bold;height:30px;line-height:30px;} +@media (min-width:760px){ +.nav{padding:0;} +.nav-inline .nav-head{padding-right:20px;} +.nav-inline li{display:inline-block;vertical-align:top;} +.nav-inline li a{padding:5px 20px;line-height:20px;display:block;} +.nav-inline .nav-more{float:right;} +.nav-split .nav-head{height:20px;line-height:20px;} +.nav-split li{border-right:solid 1px rgba(0, 0, 0, .20);} +.nav-split li a{padding:0px 20px;} +.nav-split .nav-head, .nav-split ul li, .nav-split li:last-child{border-right-width:0;} +.nav-right{text-align:right;} +.nav-right .nav-head{float:left;} +.nav.nav-justified{display:table;width:100%;} +.nav-justified .nav-head{padding:0 20px;float:none;} +.nav-justified .nav-more{float:none;} +.nav-justified li{display:table-cell;} +.nav-justified .nav-head, .nav-justified li a{text-align:center;display:block;} +.nav-justified.nav-split .nav-head{padding:0 20px;border-right-width:1px;} +.nav-big .nav-head{font-size:18px;height:30px;line-height:30px;padding:0 20px;} +.nav-big a{font-size:18px;line-height:30px;} +.nav-big.nav-split a{line-height:30px;} +} +.nav-main .nav-head{border:solid 1px #ddd;background:#ddd;padding:0 20px;line-height:28px;} +.nav-main li{margin-top:-1px;} +.nav-main a{border:solid 1px #ddd;padding:4px 20px;} +.nav-main a:hover{background:#f5f5f5;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.nav-main .active{background-color:#f5f5f5;} +.nav-main li:first-child,.nav-main li:first-child a{border-radius:4px 4px 0 0;} +.nav-main li:last-child a{border-radius:0 0 4px 4px;} +.nav-main ul li:first-child a,.nav-main ul li:last-child a{border-radius:0;} +@media (min-width:760px){ +.nav-main.nav-inline{padding:0 0 0 1px;} +.nav-main.nav-inline a{padding:4px 20px;} +.nav-main.nav-inline li{float:left;margin:0 0 0 -1px;} +.nav-main.nav-inline li:first-child,.nav-main.nav-inline li:first-child a{border-radius:4px 0 0 4px;} +.nav-main.nav-inline li:last-child a{border-radius:0 4px 4px 0;} +.nav-main.nav-inline ul li{float:none;margin:0;} +.nav-main.nav-justified .nav-head{float:none;} +.nav-main.nav-justified{width:100%;display:table;} +.nav-main.nav-justified li{width:auto;float:none;margin-left:-1px;} +.nav-main.nav-justified > li + li > a{border-left:0 none;} +.nav-main.nav-big .nav-head{height:40px;line-height:38px;} +.nav-main.nav-big.nav-inline a{line-height:30px;} +} +.nav-main.border-main .nav-head, .nav-main.border-sub .nav-head, .nav-main.border-dot .nav-head, +.nav-main.border-black .nav-head, .nav-main.border-gray .nav-head, .nav-main.border-red .nav-head, +.nav-main.border-yellow .nav-head, .nav-main.border-blue .nav-head, .nav-main.border-green .nav-head{color:#fff;} +.nav-sub .nav-head{border-bottom:solid 2px #ddd;margin-bottom:2px;padding:0 20px;height:30px;line-height:28px;} +.nav-sub a{border-bottom:solid 2px #ddd;display:block;margin-bottom:2px;border-radius:4px 4px 0 0;padding:4px 20px;} +.nav-sub a:hover{background:#f5f5f5;} +.nav-sub .active a{border-color:#333;} +@media (min-width:760px){ +.nav-sub.nav-inline li{float:left;margin:0;} +.nav-sub.nav-inline a{padding:4px 20px;margin:0;} +.nav-sub.nav-justified{width:100%;display:table;} +.nav-sub.nav-justified li{width:auto;float:none;} +.nav-sub.nav-big .nav-head{line-height:38px;height:40px;} +.nav-sub.nav-big a{line-height:30px;} +} +.nav-tabs .nav-head{line-height:30px;padding:0 20px;} +.nav-tabs a{display:block;border-radius:4px;padding:5px 20px;margin-bottom:2px;} +.nav-tabs .active a{border:solid 1px #ddd;padding-top:4px;padding-bottom:4px;} +.nav-tabs a:hover{background:#f5f5f5;} +@media (min-width:760px){ +.nav-tabs.nav-inline{border-bottom:solid 1px #ddd;position:relative;} +.nav-tabs.nav-inline .nav-head{height:29px;line-height:29px;} +.nav-tabs.nav-inline a{border-radius:4px 4px 0 0;text-align:center;margin:0;position:relative;padding-bottom:4px;} +.nav-tabs.nav-inline .active a{border-bottom:none;background:#fff;margin-bottom:-1px;padding:4px 20px 5px 20px;} +.nav-tabs.nav-big .nav-head{line-height:39px;height:39px;} +.nav-tabs.nav-big a{padding:10px 20px 9px 20px;} +.nav-tabs.nav-big .active a{padding:9px 20px 10px 20px;} +} +.nav-pills .nav-head{line-height:30px;padding:0 20px;} +.nav-pills a{display:block;border-radius:2em;margin-bottom:2px;padding:5px 20px;} +.nav-pills .active a, .nav-pills a:hover{background:#f5f5f5;} +.nav-pills .active ul a{background:#fff;} +@media (min-width:760px){ +.nav-pills.nav-inline a{margin:0;} +.nav-pills.nav-justified{width:100%;display:table;} +.nav-pills.nav-justified li{width:auto;} +.nav-pills.nav-big .nav-head{line-height:40px;height:40px;} +.nav-pills.nav-big.nav-inline a{line-height:30px;} +} +.nav-pills.border-main .active a,.nav-pills.border-sub .active a, .nav-pills.border-dot .active a,.nav-pills.border-black .active a,.nav-pills.border-gray .active a,.nav-pills.border-red .active a,.nav-pills.border-yellow .active a,.nav-pills.border-blue .active a,.nav-pills.border-green .active a{color:#fff;} +.nav.nav-sitemap{list-style:none;display:table;width:100%;margin-bottom:15px;} +.nav-sitemap ul{padding-left:0;} +.nav-sitemap li{font-weight:bold;display:table-cell;text-align:left;} +.nav-sitemap ul li{display:block;float:none;font-weight:normal;line-height:25px;} +.bg-inverse .nav{padding:5px 0;} +.bg-inverse .nav li a:hover,.bg-inverse .nav .active a{background-color:rgba(0, 0, 0, .20);color:#fff;} +.bg-inverse .nav-inline .nav-head, .bg-inverse .nav-inline li a{text-indent:1em;}/*for mobile*/ +@media (min-width:760px){ +.bg-inverse .nav{padding:0;} +.bg-inverse .nav-inline .nav-head{height:40px;line-height:40px;padding:0 20px;text-indent:0;} +.bg-inverse .nav-inline li{float:left;margin-right:1px;} +.bg-inverse .nav-inline li a{line-height:30px;padding:5px 20px;text-indent:0;} +.bg-inverse .nav-split .nav-head{border-right-width:1px;} +.bg-inverse .nav-split li{margin:0;} +.bg-inverse .nav-justified li{float:none;} +.bg-inverse .nav-inline.nav-big li a{line-height:40px;} +.bg-inverse .nav-inline.nav-big .nav-head{height:50px;line-height:50px;padding:0 20px;} +} +.bg-inverse .nav-tabs{padding:5px;} +.bg-inverse .nav-tabs .nav-head,.bg-inverse .nav-tabs li a{text-indent:0;} +.bg-inverse .nav-tabs.nav-inline,.bg-inverse .nav-tabs li a{border:none;} +.bg-inverse .nav.nav-tabs .active a,.bg-inverse .nav.nav-tabs a:hover{color:#333;background-color:#fff;padding-top:5px;padding-bottom:5px;} +@media (min-width:760px){ +.bg-inverse .nav-tabs{padding:0;} +.bg-inverse .nav-tabs li a{margin:5px 0;padding:5px 20px;line-height:20px;border-radius:4px;} +.bg-inverse .nav.nav-tabs .active a{margin:5px 0 0 0;border:none;line-height:25px;border-radius:4px 4px 0 0;} +.bg-inverse .nav.nav-tabs.nav-big a{margin:5px 0;padding:0 20px;} +.bg-inverse .nav.nav-tabs.nav-big .active a{margin:5px 0 0 0;padding:0 20px;line-height:45px;} +} +.bg-inverse .nav-pills{padding:5px;} +.bg-inverse .nav-pills .nav-head,.bg-inverse .nav-pills li a{text-indent:0;} +@media (min-width:760px){ +.bg-inverse .nav-pills{padding:0;} +.bg-inverse .nav-pills li a{line-height:20px;margin:5px 0;} +.bg-inverse .nav-pills.nav-big li a{line-height:30px;margin:5px 0;padding:5px 20px;} +} +.bg-inverse .nav-sitemap li a{text-indent:0.5em;} +.bg-inverse .nav.nav-pills .active a,.bg-inverse .nav.nav-pills.nav-inline a:hover{color:#333;background-color:#fff;} +.navbar{position:relative;} +.navbar-head{padding:5px;line-height:30px;} +.navbar-head .logo{padding:3px 0;display:block;} +.navbar-head .icon-navicon{padding:4px 12px;font-size:16px;float:right;} +.navbar-big .navbar-head .icon-navicon{margin-top:5px;} +.navbar-big .navbar-head .logo{padding:2px 0;display:block;} +.navbar p{margin:0;} +.navbar-body{border:solid 1px rgba(0, 0, 0, .2);margin-top:1px;border-top:none;display:block;background:rgba(0, 0, 0, .05);position:absolute-bak;width:100%;} +.navbar-body .nav{margin-top:-1px;padding:0;} +.navbar-body .nav a{text-indent:1em;} +.navbar-body .nav li{border-top:solid 1px rgba(0, 0, 0, .2);} +.navbar-form input{vertical-align:bottom;} +.navbar-form, .navbar-text{border-top:solid 1px rgba(0, 0, 0, .2);padding:5px 14px;margin-top:-1px;} +.navbar-body .input,.navbar-body .button{padding:4px 10px;height:30px;} +.navbar-body .nav-pills a{text-indent:0;} +@media (max-width:760px){ +.navbar-body .nav a{border-radius:0;margin-bottom:0px;} +.navbar-body .nav a:hover{background:#fff;} +} +@media (min-width:760px){ +.navbar-body,.navbar-body .nav,.navbar-form, .navbar-text{margin-top:0;border:0;} +.navbar-body .nav a{text-indent:0;} +.navbar-head{float:left;padding:0 5px 0 0;} +.navbar-body{background:transparent;margin:0;position:relative;} +.navbar-body .nav li{float:left;border:0;} +.navbar-body .nav ul li{float:none;} +.navbar-form{padding:0 10px;} +.navbar-text{padding:0;line-height:30px;} +.navbar-left{float:left;} +.navbar-right{float:right;} +.bg-inverse .navbar-head,.bg-inverse .navbar-text{padding:5px;} +.bg-inverse .navbar-form{padding:5px 10px;} +.navbar-big .navbar-head{line-height:40px;} +.navbar-big .navbar-text{padding:8px;font-size:18px;} +.navbar-big .navbar-form{padding:8px 10px;} +.navbar-big .navbar-body .input,.navbar-big .navbar-body .button{padding:5px 10px;height:34px;} +.navbar-big .nav-pills a{margin:5px 0;} +} +.nav ul{display:block;list-style:none;padding:0;} +.nav ul a{font-weight:normal;padding:5px 20px;} +.nav ul ul a{padding-left:40px;} +.nav ul ul ul a{padding-left:60px;} +.nav ul ul ul ul a{padding-left:80px;} +.nav .active ul a{font-weight:normal;} +.nav-menu .drop-menu{display:none;margin-top:-1px;} +.nav-menu ul{padding:5px 0;} +.nav-menu .arrow{display:inline-block;} +.nav-menu ul .arrow{display:none;} +.nav-menu li:hover ul{display:block;} +.nav-menu.nav-big ul a{line-height:20px;} +.nav-menu ul ul,.nav-menu.nav-main ul ul,.nav-menu.nav-sub ul ul,.nav-menu.nav-tabs ul ul,.nav-menu.nav-pills ul ul{padding:0;} +.nav-menu ul a,.nav-menu.nav-tabs ul a,.nav-menu.nav-pills .active ul a,.nav-menu.nav-big.nav-inline ul a,.bg-inverse .nav-menu.nav-inline ul a,.bg-inverse .nav-menu.nav-inline .active ul a,.bg-inverse .nav-menu.nav-inline.nav-big ul a,.bg-inverse .nav-menu.nav-inline.nav-big .active ul a,.navbar-body .nav ul a +{line-height:20px;background:#fff;font-size:inherit;border:none;border-radius:0;padding-top:5px;padding-bottom:5px;margin:0;text-indent:0;} +.nav-menu ul a,.nav-menu.nav-pills .active ul a,.bg-inverse .nav-menu ul a,.bg-inverse .nav-menu .active ul a{color:#333;} +.navbar-body .nav ul li{border:0;} +@media (min-width:760px){ +.nav-menu ul{position:absolute;display:none;left:100%;top:-6px;z-index:1;float:left;min-width:160px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, .15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175);box-shadow:0 6px 12px rgba(0, 0, 0, .175);} +.nav-menu .arrow{display:inline-block;float:right;margin-top:6px;border-left:4px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;} +.nav-menu ul .arrow{margin:6px -10px 0 0;display:inline-block;} +.nav-menu ul a,.nav-menu ul ul a,.nav-menu ul ul ul a,.nav-menu ul ul ul ul a{padding-left:20px;} +.nav-menu ul ul{padding:5px 0;} +.nav-menu li:hover ul ul, .nav-menu li:hover ul ul ul, .nav-menu li:hover ul ul ul ul{display:none;} +.nav-menu li:hover ul, .nav-menu li li:hover ul, .nav-menu li li li:hover ul, .nav-menu li li li li:hover ul{display:block;} +.nav-inline.nav-menu ul{top:100%;left:0;} +.nav-inline.nav-menu ul li{display:block;} +.nav-inline.nav-menu ul ul{top:-6px;left:100%;} +.nav-inline.nav-menu ul a{display:block;padding:5px 20px;text-align:left;font-size:inherit;} +.nav-inline.nav-menu ul a:hover{background:#f5f5f5;} +.nav-inline.nav-menu .arrow{float:none;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent;margin-top:0;} +.nav-inline.nav-menu ul .arrow{float:right;margin-top:6px;border-left:4px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;} +.nav-main .arrow,.nav-main.nav-inline ul .arrow,.nav-sub .arrow,.nav-sub.nav-inline ul .arrow,.nav-tabs .arrow,.nav-tabs.nav-inline ul .arrow,.nav-pills .arrow,.nav-pills.nav-inline ul .arrow{margin-right:-10px;} +.nav-main.nav-inline .arrow,.nav-sub.nav-inline .arrow,.nav-tabs.nav-inline .arrow,.nav-pills.nav-inline .arrow{margin-right:0;} +.nav-menu ul ul,.nav-menu.nav-main ul ul,.nav-menu.nav-sub ul ul,.nav-menu.nav-tabs ul ul,.nav-menu.nav-pills ul ul{padding:5px 0;} +.nav-main.nav-inline ul li,.nav-sub.nav-inline ul li,.bg-inverse .nav-inline ul li{float:none;} +} +.fixed-top{position:fixed;top:0;} +.fixed-bottom{position:fixed;bottom:0;} +.fixed-left{position:fixed;left:0;} +.fixed-right{position:fixed;right:0;} +.fixed-top-left{position:fixed;top:0;left:0;} +.fixed-top-right{position:fixed;top:0;right:0;} +.fixed-bottom-left{position:fixed;bottom:0;left:0;} +.fixed-bottom-right{position:fixed;bottom:0;right:0;} +.bread{border-radius:4px;padding:8px 15px;font-size:12px;margin-bottom:15px;color:#999;} +.bread li{display:inline-block;} +.bread li:after{content:"\002f";padding:0 8px;color:#ddd;} +.bread li:last-child:after{content:"";} +.step{position:relative;height:10px;border-radius:5px;background-color:#f5f5f5;margin-bottom:30px;border-radius:5px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, .1);} +.step-bar{position:relative;height:10px;float:left;display:inline-block;text-align:center;color:#aaa;} +.step-bar:first-child{border-radius:5px 0 0 5px;} +.step-bar:last-child{border-radius:0 5px 5px 0;} +.step-point{position:relative;display:inline-block;width:20px;height:20px;line-height:20px;top:-5px;border-radius:50%;color:#fff;background-color:#bbb;-webkit-box-shadow:1px 1px 1px rgba(0, 0, 0, .175);box-shadow:1px 1px 1px rgba(0, 0, 0, .175);} +.step-text{display:block;} +.step .complete, .step .complete .step-point{background:#cf9;} +.step .active, .step .active .step-point{background:#0a0;} +.list-text{list-style:inside;padding:0;} +.list-text li{line-height:24px;} +.list-text .date{font-size:12px;float:right;} +.list-text .divider{list-style-type:none;background-color:#ddd;height:1px;overflow:hidden;margin:15px 0;} +.list-text.list-underline{list-style:outside;padding-left:15px;} +.list-text.list-underline li{border-bottom:solid 1px #ddd;line-height:36px;} +.list-underline.list-striped li{padding:0 10px;} +.list-text.list-striped{list-style:none;padding:0;} +.list-box a{background-color:#f5f5f5;display:block;padding:15px;height:150px;text-align:justify;font-size:16px;text-overflow:ellipsis;overflow:hidden;} +.list-box .date{display:block;font-size:12px;} +.list-media{list-style:none;padding:0;} +.list-media li{margin-bottom:10px;} +.list-media.list-underline li{padding-bottom:15px;border-bottom:solid 1px #ddd;line-height:inherit;} +.pagination{list-style:none;margin:0;padding:0;display:inline-block;vertical-align:bottom;} +.pagination li{display:inline-block;border:solid 1px #ddd;border-radius:4px;} +.pagination a{color:#333;padding:8px 12px;line-height:18px;display:block;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.pagination .disabled a:link, .pagination .disabled a:visited, .pagination .disabled a:hover{cursor:not-allowed;pointer-events:none;color:#ddd;} +.pagination .active{pointer-events:none;} +.pagination .active,.pagination a:hover{background:#f5f5f5;border-radius:4px;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.pagination-group{border-right:solid 1px #ddd;border-radius:4px;} +.pagination-group li{float:left;border-right:none;border-radius:0;} +.pagination-group li:not(:first-child):not(:last-child){border-radius:0;} +.pagination-group li:first-child{border-radius:4px 0 0 4px;} +.pagination-group li:last-child{border-radius:0 4px 4px 0;} +.pagination-group .active,.pagination-group a:hover{background:#f5f5f5;border-radius:0;} +.pagination-big a{padding:10px 16px;font-size:16px;} +.pagination-small a{padding:5px 10px;font-size:12px;} +.pagination.border-main .active a, .pagination.border-sub .active a, .pagination.border-dot .active a, +.pagination.border-black .active a, .pagination.border-gray .active a, .pagination.border-red .active a, +.pagination.border-yellow .active a, .pagination.border-blue .active a, .pagination.border-green .active a{color:#fff;} +.pager{list-style:none;padding:0;text-align:center;clear:both;} +.pager li{display:inline-block;} +.pager li a{color:#333;border:solid 1px #ddd;border-radius:15px;padding:5px 15px;transition:all 1s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.pager li a:hover{background-color:#f5f5f5;transition:all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1) 0s;} +.pager-prev, .pager .pager-prev, .pager-next, .pager .pager-next{font-size:36px;padding:0;color:#ddd;border:solid 1px #ddd;background-color:rgba(255, 255, 255, .2);width:50px;height:50px;line-height:45px;display:inline-block;border-radius:50%;text-align:center;cursor:pointer;} +.pager-prev:hover, .pager-next:hover{background-color:rgba(0, 0, 0, .2);} +.pager-group li{float:left;display:inline-block;} +.pager-group li:not(:first-child):not(:last-child){border-radius:0;} +.pager-group li a:first-child{border-radius:4px 0 0 4px;} +.pager-group li a:last-child{border-radius:0 4px 4px 0;} +.pointer{padding:0px;} +.pointer li{border:solid 1px #ddd;width:10px;height:10px;margin:1px;display:inline-block;border-radius:10px;cursor:pointer;} +.pointer .active{border:none;background:#ddd;width:12px;height:12px;margin:0;} +.keypoint{padding:50px;} +.keypoint h1{font-size:48px;margin-bottom:15px;} +.keypoint p{font-size:18px;} +.detail h1{text-align:center;} +.detail p{text-indent:2em;} +h1,.h1{font-size:24px;} +h2,.h2{font-size:20px;} +h3,.h3{font-size:18px;} +h4,.h4{font-size:16px;} +h5,.h5{font-size:14px;} +h6,.h6{font-size:12px;} +h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small{font-size:60%;filter:alpha(opacity=60);opacity:.6;} +h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small{font-size:12px;filter:alpha(opacity=60);opacity:.6;} +p,.p{margin-bottom:15px;line-height:24px;} +.text-indent,.text-indent p,.text-indent div{text-indent:2em;} +.text-left{text-align:left;} +.text-center{text-align:center;} +.text-right{text-align:right;} +.text-justify{text-align:justify;} +.text-large{font-size:24px;} +.text-big{font-size:16px;} +.text-default{font-size:14px;} +.text-small{font-size:12px;} +.text-little{font-size:10px;} +.height-large{line-height:40px;} +.height-big{line-height:30px;} +.height{line-height:24px;} +.height-small{line-height:20px;} +.height-little{line-height:16px;} +.border{border:solid 1px #ddd;} +.border-top{border-top:solid 1px #ddd;} +.border-right{border-right:solid 1px #ddd;} +.border-bottom{border-bottom:solid 1px #ddd;} +.border-left{border-left:solid 1px #ddd;} +.border-left-right{border-left:solid 1px #ddd;border-right:solid 1px #ddd;} +.border-top-bottom{border-top:solid 1px #ddd;border-bottom:solid 1px #ddd;} +.border-large{border-width:10px;} +.border-big{border-width:5px;} +.border-middle{border-width:3px;} +.border-small{border-width:2px;} +hr{background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:1px;margin:10px 0;border:none;-moz-box-sizing:content-box;box-sizing:content-box;} +hr.space{background:#fff;color:#fff;visibility:hidden;} +.img-border{border:solid 1px #ddd;padding:4px;} +.img-responsive{display:block;max-width:100%;height:auto;} +ul{padding-left:20px;} +ol{padding-left:24px;} +.list-cn{list-style-type:cjk-ideographic;} +.list-alpha{list-style-type:upper-alpha;} +.list-unstyle{list-style:none;padding-left:0;} +.list-unstyle ul{list-style:disc;} +.list-inline li{display:inline-block;padding:0 10px;width:auto;} +dt{font-weight:bold;} +dd{padding:8px 0 15px 0;} +@media (min-width:760px){ +.dl-inline dt{width:15%;display:inline-block;float:left;text-align:right;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;} +.dl-inline dd{width:85%;display:inline-block;float:left;padding:0 0 15px 15px;} +} +.table{width:100%;max-width:100%;border-collapse:collapse;border-spacing:0;} +.table th{border-bottom:2px solid #ddd;vertical-align:bottom;padding:8px;text-align:left;} +.table td{border-top:1px solid #ddd;padding:8px;vertical-align:top;} +.table-striped > tbody > tr:nth-child(odd) > td, .table-striped > tbody > tr:nth-child(odd) > th{background-color:#f9f9f9;}/*条纹-IE9以下无效果*/ +.table-bordered th,.table-bordered td{border:solid 1px #ddd;} +.table-bordered th{border-bottom:2px solid #ddd;} +.table-hover > tbody > tr:hover > td,.table-hover > tbody > tr:hover > th{background-color:#f9f9f9;}/*不支持IE6*/ +.table-condensed th,.table-condensed td{padding:5px;} +@media (max-width:760px){ +.table-responsive{width:100%;overflow-x:scroll;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;} +.table-responsive .table tr th, .table-responsive .table tr td{white-space:nowrap;} +} +blockquote{border:solid 1px #ddd;border-left-width:6px;padding:20px;border-radius:4px;} +blockquote strong{display:block;font-size:16px;margin-bottom:10px;} +blockquote p:last-child{margin:0;} +.quote-floatright{border-left-width:1px;border-right-width:6px;text-align:right;} +.float-left{float:left !important;} +.float-right{float:right !important;} +.clearfix:after, .layout:after, .container:after, .container-layout:after, .line:after, .line-small:after, .line-middle:after, .line-big:after, .nav-main:after, .nav-sub:after, .navbar:after{content:" ";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} +.clearfix, .layout, .container, .container-layout, .line, .line-small, .line-middle, .line-big, .nav-main, .nav-sub, .navbar{display:block;} +.clear{clear:both;} +.print-show{display:none !important;} +@media print{ + .print-show{display:block !important;} + table.print-show{display:table;} + tr.print-show{display:table-row !important;} + th.print-show,td.print-show{display:table-cell !important;} + .print-hidden{display:none !important;} +} +.show{display:block !important;} +.hidden{display:none !important;visibility:hidden !important;} +.padding-large{padding:30px;} +.padding-large-top{padding-top:30px;} +.padding-large-right{padding-right:30px;} +.padding-large-bottom{padding-bottom:30px;} +.padding-large-left{padding-left:30px;} +.padding-big{padding:20px;} +.padding-big-top{padding-top:20px;} +.padding-big-right{padding-right:20px;} +.padding-big-bottom{padding-bottom:20px;} +.padding-big-left{padding-left:20px;} +.padding{padding:10px;} +.padding-top{padding-top:10px;} +.padding-right{padding-right:10px;} +.padding-bottom{padding-bottom:10px;} +.padding-left{padding-left:10px;} +.padding-small{padding:5px;} +.padding-small-top{padding-top:5px;} +.padding-small-right{padding-right:5px;} +.padding-small-bottom{padding-bottom:5px;} +.padding-small-left{padding-left:5px;} +.padding-little{padding:2px;} +.padding-little-top{padding-top:2px;} +.padding-little-right{padding-right:2px;} +.padding-little-bottom{padding-bottom:2px;} +.padding-little-left{padding-left:2px;} +.margin-large{margin:30px;} +.margin-large-top{margin-top:30px;} +.margin-large-right{margin-right:30px;} +.margin-large-bottom{margin-bottom:30px;} +.margin-large-left{margin-left:30px;} +.margin-big{margin:20px;} +.margin-big-top{margin-top:20px;} +.margin-big-right{margin-right:20px;} +.margin-big-bottom{margin-bottom:20px;} +.margin-big-left{margin-left:20px;} +.margin{margin:10px !important;clear:both;} +.margin-top{margin-top:10px;} +.margin-right{margin-right:10px;} +.margin-bottom{margin-bottom:10px;} +.margin-left{margin-left:10px;} +.margin-small{margin:5px;} +.margin-small-top{margin-top:5px;} +.margin-small-right{margin-right:5px;} +.margin-small-bottom{margin-bottom:5px;} +.margin-small-left{margin-left:5px;} +.margin-little{margin:2px;} +.margin-little-top{margin-top:2px;} +.margin-little-right{margin-right:2px;} +.margin-little-bottom{margin-bottom:2px;} +.margin-little-left{margin-left:2px;} +.radius-none{border-radius:0;} +.radius-small{border-radius:2px;} +.radius{border-radius:4px;} +.radius-big{border-radius:6px;} +.radius-rounded{border-radius:2em;padding-left:1em;padding-right:1em;} +.radius-circle{border-radius:50%;} +.bounce,.bounce-hover,.flash,.flash-hover,.shake,.shake-hover,.swing,.swing-hover,.wobble,.wobble-hover,.ring,.ring-hover{-webkit-animation:1s ease;-moz-animation:1s ease;-ms-animation:1s ease;animation:1s ease;} +.fadein,.fadein-top,.fadein-right,.fadein-bottom,.fadein-left,.bouncein,.rotatein{-webkit-animation:1s ease-out backwards;-moz-animation:1s ease-out backwards;-ms-animation:1s ease-out backwards;animation:1s ease-out backwards;} +.fadeout,.fadeout-top,.fadeout-right,.fadeout-bottom,.fadeout-left,.bounceout,.rotateout{-webkit-animation:1s ease-in forwards;-moz-animation:1s ease-in forwards;-ms-animation:1s ease-in forwards;animation:1s ease-in forwards;} +.rotate,.rotate-hover{-webkit-animation:2s infinite linear;-moz-animation:2s infinite linear;-ms-animation:2s infinite linear;animation:2s infinite linear;} +.fadein{-webkit-animation-name:a-fadein;-moz-animation-name:a-fadein;-ms-animation-name:a-fadein;animation-name:a-fadein;} +@-webkit-keyframes a-fadein{0%{opacity:0;}100%{opacity:1;}} +@-moz-keyframes a-fadein{0%{opacity:0;}100%{opacity:1;}} +@-ms-keyframes a-fadein{0%{opacity:0;}100%{opacity:1;}} +@keyframes a-fadein{0%{opacity:0;}100%{opacity:1;}} +.fadein-top{-webkit-animation-name:fadeinT;-moz-animation-name:fadeinT;-ms-animation-name:fadeinT;animation-name:fadeinT;} +@-webkit-keyframes fadeinT{0%{opacity:0;-webkit-transform:translateY(-50px);}100%{opacity:1;-webkit-transform:translateY(0);}} +@-moz-keyframes fadeinT{0%{opacity:0;-moz-transform:translateY(-50px);}100%{opacity:1;-moz-transform:translateY(0);}} +@-ms-keyframes fadeinT{0%{opacity:0;-ms-transform:translateY(-50px);}100%{opacity:1;-ms-transform:translateY(0);}} +@keyframes fadeinT{0%{opacity:0;transform:translateY(-50px);}100%{opacity:1;transform:translateY(0);}} +.fadein-right{-webkit-animation-name:fadeinR;-moz-animation-name:fadeinR;-ms-animation-name:fadeinR;animation-name:fadeinR;} +@-webkit-keyframes fadeinR{0%{opacity:0;-webkit-transform:translateX(50px);}100%{opacity:1;-webkit-transform:translateX(0);}} +@-moz-keyframes fadeinR{0%{opacity:0;-moz-transform:translateX(50px);}100%{opacity:1;-moz-transform:translateX(0);}} +@-ms-keyframes fadeinR{0%{opacity:0;-ms-transform:translateX(50px);}100%{opacity:1;-ms-transform:translateX(0);}} +@keyframes fadeinR{0%{opacity:0;transform:translateX(50px);}100%{opacity:1;transform:translateX(0);}} +.fadein-bottom{-webkit-animation-name:fadeinB;-moz-animation-name:fadeinB;-ms-animation-name:fadeinB;animation-name:fadeinB;} +@-webkit-keyframes fadeinB{0%{opacity:0;-webkit-transform:translateY(50px);}100%{opacity:1;-webkit-transform:translateY(0);}} +@-moz-keyframes fadeinB{0%{opacity:0;-moz-transform:translateY(50px);}100%{opacity:1;-moz-transform:translateY(0);}} +@-ms-keyframes fadeinB{0%{opacity:0;-ms-transform:translateY(50px);}100%{opacity:1;-ms-transform:translateY(0);}} +@keyframes fadeinB{0%{opacity:0;transform:translateY(50px);}100%{opacity:1;transform:translateY(0);}} +.fadein-left{-webkit-animation-name:fadeinL;-moz-animation-name:fadeinL;-ms-animation-name:fadeinL;animation-name:fadeinL;} +@-webkit-keyframes fadeinL{0%{opacity:0;-webkit-transform:translateX(-50px);}100%{opacity:1;-webkit-transform:translateX(0);}} +@-moz-keyframes fadeinL{0%{opacity:0;-moz-transform:translateX(-50px);}100%{opacity:1;-moz-transform:translateX(0);}} +@-ms-keyframes fadeinL{0%{opacity:0;-ms-transform:translateX(-50px);}100%{opacity:1;-ms-transform:translateX(0);}} +@keyframes fadeinL{0%{opacity:0;transform:translateX(-50px);}100%{opacity:1;transform:translateX(0);}} +.fadeout{-webkit-animation-name:a-fadeout;-moz-animation-name:a-fadeout;-ms-animation-name:a-fadeout;animation-name:a-fadeout;} +@-webkit-keyframes a-fadeout{0%{opacity:1;}100%{opacity:0;}} +@-moz-keyframes a-fadeout{0%{opacity:1;}100%{opacity:0;}} +@-ms-keyframes a-fadeout{0%{opacity:1;}100%{opacity:0;}} +@keyframes a-fadeout{0%{opacity:1;}100%{opacity:0;}} +.fadeout-top{-webkit-animation-name:fadeoutT;-moz-animation-name:fadeoutT;-ms-animation-name:fadeoutT;animation-name:fadeoutT;} +@-webkit-keyframes fadeoutT{0%{opacity:1;-webkit-transform:translateY(0);}100%{opacity:0;-webkit-transform:translateY(-100px);}} +@-moz-keyframes fadeoutT{0%{opacity:1;-moz-transform:translateY(0);}100%{opacity:0;-moz-transform:translateY(-100px);}} +@-ms-keyframes fadeoutT{0%{opacity:1;-ms-transform:translateY(0);}100%{opacity:0;-ms-transform:translateY(-100px);}} +@keyframes fadeoutT{0%{opacity:1;transform:translateY(0);}100%{opacity:0;transform:translateY(-100px);}} +.fadeout-right{-webkit-animation-name:fadeoutR;-moz-animation-name:fadeoutR;-ms-animation-name:fadeoutR;animation-name:fadeoutR;} +@-webkit-keyframes fadeoutR{0%{opacity:1;-webkit-transform:translateX(0);}100%{opacity:0;-webkit-transform:translateX(100px);}} +@-moz-keyframes fadeoutR{0%{opacity:1;-moz-transform:translateX(0);}100%{opacity:0;-moz-transform:translateX(100px);}} +@-ms-keyframes fadeoutR{0%{opacity:1;-ms-transform:translateX(0);}100%{opacity:0;-ms-transform:translateX(100px);}} +@keyframes fadeoutR{0%{opacity:1;transform:translateX(0);}100%{opacity:0;transform:translateX(100px);}} +.fadeout-bottom{-webkit-animation-name:fadeoutB;-moz-animation-name:fadeoutB;-ms-animation-name:fadeoutB;animation-name:fadeoutB;} +@-webkit-keyframes fadeoutB{0%{opacity:1;-webkit-transform:translateY(0);}100%{opacity:0;-webkit-transform:translateY(100px);}} +@-moz-keyframes fadeoutB{0%{opacity:1;-moz-transform:translateY(0);}100%{opacity:0;-moz-transform:translateY(100px);}} +@-ms-keyframes fadeoutB{0%{opacity:1;-ms-transform:translateY(0);}100%{opacity:0;-ms-transform:translateY(100px);}} +@keyframes fadeoutB{0%{opacity:1;transform:translateY(0);}100%{opacity:0;transform:translateY(100px);}} +.fadeout-left{-webkit-animation-name:fadeoutL;-moz-animation-name:fadeoutL;-ms-animation-name:fadeoutL;animation-name:fadeoutL;} +@-webkit-keyframes fadeoutL{0%{opacity:1;-webkit-transform:translateX(0);}100%{opacity:0;-webkit-transform:translateX(-100px);}} +@-moz-keyframes fadeoutL{0%{opacity:1;-moz-transform:translateX(0);}100%{opacity:0;-moz-transform:translateX(-100px);}} +@-ms-keyframes fadeoutL{0%{opacity:1;-ms-transform:translateX(0);}100%{opacity:0;-ms-transform:translateX(-100px);}} +@keyframes fadeoutL{0%{opacity:1;transform:translateX(0);}100%{opacity:0;transform:translateX(-100px);}} +.bounce,.bounce-hover:hover{-webkit-animation-name:a-bounce;-moz-animation-name:a-bounce;-ms-animation-name:a-bounce;animation-name:a-bounce;} +@-webkit-keyframes a-bounce{0%,20%,50%,80%,100%{-webkit-transform:translateY(0);}40%{-webkit-transform:translateY(-30px);}60%{-webkit-transform:translateY(-15px);}} +@-moz-keyframes a-bounce{0%,20%,50%,80%,100%{-moz-transform:translateY(0);}40%{-moz-transform:translateY(-30px);}60%{-moz-transform:translateY(-15px);}} +@-ms-keyframes a-bounce{0%,20%,50%,80%,100%{-ms-transform:translateY(0);}40%{-ms-transform:translateY(-30px);}60%{-ms-transform:translateY(-15px);}} +@keyframes a-bounce{0%,20%,50%,80%,100%{transform:translateY(0);}40%{transform:translateY(-30px);}60%{transform:translateY(-15px);}} +.bouncein{-webkit-animation-name:a-bouncein;-moz-animation-name:a-bouncein;-ms-animation-name:a-bouncein;animation-name:a-bouncein;} +@-webkit-keyframes a-bouncein{0%{opacity:0;-webkit-transform:scale(0.3);}50%{opacity:1;-webkit-transform:scale(1.05);}70%{-webkit-transform:scale(0.9);}100%{-webkit-transform:scale(1);}} +@-moz-keyframes a-bouncein{0%{opacity:0;-moz-transform:scale(0.3);}50%{opacity:1;-moz-transform:scale(1.05);}70%{-moz-transform:scale(0.9);}100%{-moz-transform:scale(1);}} +@-ms-keyframes a-bouncein{0%{opacity:0;-ms-transform:scale(0.3);}50%{opacity:1;-ms-transform:scale(1.05);}70%{-ms-transform:scale(0.9);}100%{-ms-transform:scale(1);}} +@keyframes a-bouncein{0%{opacity:0;transform:scale(0.3);}50%{opacity:1;transform:scale(1.05);}70%{transform:scale(0.9);}100%{transform:scale(1);}} +.bounceout{-webkit-animation-name:a-bounceout;-moz-animation-name:a-bounceout;-ms-animation-name:a-bounceout;animation-name:a-bounceout;} +@-webkit-keyframes a-bounceout{0%{-webkit-transform:scale(1);}25%{-webkit-transform:scale(0.95);}50%{opacity:1;-webkit-transform:scale(1.1);}100%{opacity:0;-webkit-transform:scale(0.3);}} +@-moz-keyframes a-bounceout{0%{-moz-transform:scale(1);}25%{-moz-transform:scale(0.95);}50%{opacity:1;-moz-transform:scale(1.1);}100%{opacity:0;-moz-transform:scale(0.3);}} +@-ms-keyframes a-bounceout{0%{-ms-transform:scale(1);}25%{-ms-transform:scale(0.95);}50%{opacity:1;-ms-transform:scale(1.1);}100%{opacity:0;-ms-transform:scale(0.3);}} +@keyframes a-bounceout{0%{transform:scale(1);}25%{transform:scale(0.95);}50%{opacity:1;transform:scale(1.1);}100%{opacity:0;transform:scale(0.3);}} +.rotatein{-webkit-animation-name:a-rotatein;-moz-animation-name:a-rotatein;-ms-animation-name:a-rotatein;animation-name:a-rotatein;} +@-webkit-keyframes a-rotatein{0%{opacity:0;-webkit-transform:rotate(-200deg);}100%{opacity:1;-webkit-transform:rotate(0);}} +@-moz-keyframes a-rotatein{0%{opacity:0;-moz-transform:rotate(-200deg);}100%{opacity:1;-moz-transform:rotate(0);}} +@-ms-keyframes a-rotatein{0%{opacity:0;-ms-transform:rotate(-200deg);}100%{opacity:1;-ms-transform:rotate(0);}} +@keyframes a-rotatein{0%{opacity:0;transform:rotate(-200deg);}100%{opacity:1;transform:rotate(0);}} +.rotateout{-webkit-animation-name:a-rotateout;-moz-animation-name:a-rotateout;-ms-animation-name:a-rotateout;animation-name:a-rotateout;} +@-webkit-keyframes a-rotateout{0%{-webkit-transform-origin:center center;-webkit-transform:rotate(0);opacity:1;}100%{-webkit-transform-origin:center center;-webkit-transform:rotate(200deg);opacity:0;}} +@-moz-keyframes a-rotateout{0%{-moz-transform-origin:center center;-moz-transform:rotate(0);opacity:1;}100%{-moz-transform-origin:center center;-moz-transform:rotate(200deg);opacity:0;}} +@-ms-keyframes a-rotateout{0%{-ms-transform-origin:center center;-ms-transform:rotate(0);opacity:1;}100%{-ms-transform-origin:center center;-ms-transform:rotate(200deg);opacity:0;}} +@keyframes a-rotateout{0%{transform-origin:center center;transform:rotate(0);opacity:1;}100%{transform-origin:center center;transform:rotate(200deg);opacity:0;}} +.flash,.flash-hover:hover{-webkit-animation-name:a-flash;-moz-animation-name:a-flash;-ms-animation-name:a-flash;animation-name:a-flash;} +@-webkit-keyframes a-flash{0%,50%,100%{opacity:1;}25%,75%{opacity:0;}} +@-moz-keyframes a-flash{0%,50%,100%{opacity:1;}25%,75%{opacity:0;}} +@-ms-keyframes a-flash{0%,50%,100%{opacity:1;}25%,75%{opacity:0;}} +@keyframes a-flash{0%,50%,100%{opacity:1;}25%,75%{opacity:0;}} +.shake,.shake-hover:hover{-webkit-animation-name:a-shake;-moz-animation-name:a-shake;-ms-animation-name:a-shake;animation-name:a-shake;} +@-webkit-keyframes a-shake{0%,100%{-webkit-transform:translateX(0);}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);}20%,40%,60%,80%{-webkit-transform:translateX(10px);}} +@-moz-keyframes a-shake{0%,100%{-moz-transform:translateX(0);}10%,30%,50%,70%,90%{-moz-transform:translateX(-10px);}20%,40%,60%,80%{-moz-transform:translateX(10px);}} +@-ms-keyframes a-shake{0%,100%{-ms-transform:translateX(0);}10%,30%,50%,70%,90%{-ms-transform:translateX(-10px);}20%,40%,60%,80%{-ms-transform:translateX(10px);}} +@keyframes a-shake{0%,100%{transform:translateX(0);}10%,30%,50%,70%,90%{transform:translateX(-10px);}20%,40%,60%,80%{transform:translateX(10px);}} +.swing,.swing-hover:hover{-webkit-animation-name:a-swing;-moz-animation-name:a-swing;-ms-animation-name:a-swing;animation-name:a-swing;} +@-webkit-keyframes a-swing{20%{-webkit-transform:rotate(15deg);}40%{-webkit-transform:rotate(-10deg);}60%{-webkit-transform:rotate(5deg);}80%{-webkit-transform:rotate(-5deg);}100%{-webkit-transform:rotate(0);}} +@-moz-keyframes a-swing{20%{-moz-transform:rotate(15deg);}40%{-moz-transform:rotate(-10deg);}60%{-moz-transform:rotate(5deg);}80%{-moz-transform:rotate(-5deg);}100%{-moz-transform:rotate(0);}} +@-ms-keyframes a-swing{20%{-ms-transform:rotate(15deg);}40%{-ms-transform:rotate(-10deg);}60%{-ms-transform:rotate(5deg);}80%{-ms-transform:rotate(-5deg);}100%{-ms-transform:rotate(0);}} +@keyframes a-swing{20%{transform:rotate(15deg);}40%{transform:rotate(-10deg);}60%{transform:rotate(5deg);}80%{transform:rotate(-5deg);}100%{transform:rotate(0);}} +.wobble,.wobble-hover:hover{-webkit-animation-name:a-wobble;-moz-animation-name:a-wobble;-ms-animation-name:a-wobble;animation-name:a-wobble;} +@-webkit-keyframes a-wobble{0%{-webkit-transform:translateX(0);}15%{-webkit-transform:translateX(-50px) rotate(-5deg);}30%{-webkit-transform:translateX(40px) rotate(3deg);}45%{-webkit-transform:translateX(-33px) rotate(-3deg);}60%{-webkit-transform:translateX(10px) rotate(2deg);}75%{-webkit-transform:translateX(-10px) rotate(-1deg);}100%{-webkit-transform:translateX(0);}} +@-moz-keyframes a-wobble{0%{-moz-transform:translateX(0);}15%{-moz-transform:translateX(-50px) rotate(-5deg);}30%{-moz-transform:translateX(40px) rotate(3deg);}45%{-moz-transform:translateX(-33px) rotate(-3deg);}60%{-moz-transform:translateX(10px) rotate(2deg);}75%{-moz-transform:translateX(-10px) rotate(-1deg);}100%{-moz-transform:translateX(0);}} +@-ms-keyframes a-wobble{0%{-ms-transform:translateX(0);}15%{-ms-transform:translateX(-50px) rotate(-5deg);}30%{-ms-transform:translateX(40px) rotate(3deg);}45%{-ms-transform:translateX(-33px) rotate(-3deg);}60%{-ms-transform:translateX(10px) rotate(2deg);}75%{-ms-transform:translateX(-10px) rotate(-1deg);}100%{-ms-transform:translateX(0);}} +@keyframes a-wobble{0%{transform:translateX(0);}15%{transform:translateX(-50px) rotate(-5deg);}30%{transform:translateX(40px) rotate(3deg);}45%{transform:translateX(-33px) rotate(-3deg);}60%{transform:translateX(10px) rotate(2deg);}75%{transform:translateX(-10px) rotate(-1deg);}100%{transform:translateX(0);}} +.ring,.ring-hover:hover{-webkit-animation-name:a-ring;-moz-animation-name:a-ring;-ms-animation-name:a-ring;animation-name:a-ring;} +@-webkit-keyframes a-ring{0%{-webkit-transform:scale(1);}10%,20%{-webkit-transform:scale(0.9) rotate(-3deg);}30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg);}40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg);}100%{-webkit-transform:scale(1) rotate(0);}} +@-moz-keyframes a-ring{0%{-moz-transform:scale(1);}10%,20%{-moz-transform:scale(0.9) rotate(-3deg);}30%,50%,70%,90%{-moz-transform:scale(1.1) rotate(3deg);}40%,60%,80%{-moz-transform:scale(1.1) rotate(-3deg);}100%{-moz-transform:scale(1) rotate(0);}} +@-ms-keyframes a-ring{0%{-ms-transform:scale(1);}10%,20%{-ms-transform:scale(0.9) rotate(-3deg);}30%,50%,70%,90%{-ms-transform:scale(1.1) rotate(3deg);}40%,60%,80%{-ms-transform:scale(1.1) rotate(-3deg);}100%{-ms-transform:scale(1) rotate(0);}} +@keyframes a-ring{0%{transform:scale(1);}10%,20%{transform:scale(0.9) rotate(-3deg);}30%,50%,70%,90%{transform:scale(1.1) rotate(3deg);}40%,60%,80%{transform:scale(1.1) rotate(-3deg);}100%{transform:scale(1) rotate(0);}} +.rotate,.rotate-hover:hover{-webkit-animation-name:a-rotate;-moz-animation-name:a-rotate;-ms-animation-name:a-rotate;animation-name:a-rotate;} +@-webkit-keyframes a-rotate{0%{-webkit-transform:rotate(0deg);}100%{-webkit-transform:rotate(359deg);}} +@-moz-keyframes a-rotate{0%{-moz-transform:rotate(0deg);}100%{-moz-transform:rotate(359deg);}} +@-ms-keyframes a-rotate{0%{-ms-transform:rotate(0deg);}100%{-ms-transform:rotate(359deg);}} +@keyframes a-rotate{0%{transform:rotate(0deg);}100%{transform:rotate(359deg);}} +.text-black, a.text-black:link, a.text-black:visited,.button.border-black,blockquote.border-black strong,.pager.border-black a,.pager-prev.border-black,.pager-next.border-black +{color:#000;} +a.text-black:hover{color:#666;} +.text-gray, a.text-gray:link, a.text-gray:visited,.button.border-gray,blockquote.border-gray strong,.pager.border-gray a,.pager-prev.border-gray,.pager-next.border-gray +{color:#999;} +.text-white, a.text-white:link, a.text-white:visited,.button.border-white,blockquote.border-white,.pager.border-white a,.pager-prev.border-white,.pager-next.border-white +{color:#fff;} +.text-red, a.text-red:link, a.text-red:visited,.button.border-red,.button.bg-red-light,blockquote.border-red strong,.pager.border-red a,.pager-prev.border-red,.pager-next.border-red,.badge.bg-red-light,.alert-red,.check-error +{color:#e33;} +.text-yellow, a.text-yellow:link, a.text-yellow:visited,.button.border-yellow,.button.bg-yellow-light,blockquote.border-yellow strong,.pager.border-yellow a,.pager-prev.border-yellow,.pager-next.border-yellow,.badge.bg-yellow-light,.alert-yellow,.check-warning +{color:#f60;} +.text-blue, a.text-blue:link, a.text-blue:visited,.button.border-blue,.button.bg-blue-light,blockquote.border-blue strong,.pager.border-blue a,.pager-prev.border-blue,.pager-next.border-blue,.badge.bg-blue-light,.alert-blue +{color:#0ae;} +.text-green, a.text-green:link, a.text-green:visited,.button.border-green,.button.bg-green-light,blockquote.border-green strong,.pager.border-green a,.pager-prev.border-green,.pager-next.border-green,.badge.bg-green-light,.alert-green,.check-success +{color:#2c7;} +.text-red-light, a.text-red-light:link, a.text-red-light:visited,.button.border-red-light,blockquote.border-red-light strong,.pager.border-red-light a +{color:#fdc;} +.text-yellow-light, a.text-yellow-light:link, a.text-yellow-light:visited,.button.border-yellow-light,blockquote.border-yellow-light strong,.pager.border-yellow-light a,.pager-prev.border-yellow-light,.pager-next.border-yellow-light +{color:#fec;} +.text-blue-light, a.text-blue-light:link, a.text-blue-light:visited,.button.border-blue-light,blockquote.border-blue-light strong,.pager.border-blue-light a,.pager-prev.border-blue-light,.pager-next.border-blue-light +{color:#def;} +.text-green-light, a.text-green-light:link, a.text-green-light:visited,.button.border-green-light,blockquote.border-green-light strong,.pager.border-green-light a,.pager-prev.border-green-light,.pager-next.border-green-light +{color:#ded;} +.bg-inverse, .bg-inverse a{color:#fff;} +a.text-white:hover, .bg-inverse a:hover{color:#ddd;} +.bg,.table .current, .table .current td,.table .current th,.button.active,.pointer.border .active,.nav-menu ul a:hover,.nav-menu.nav-pills .active ul a:hover,.bg-inverse .nav.nav-menu ul a:hover,.bg-inverse .nav.nav-menu .active ul a:hover,.bg-inverse .nav.nav-menu.nav-tabs ul a:hover,.bg-inverse .nav.nav-menu.nav-pills ul a:hover,.bg-inverse .nav-menu.nav-inline.nav-big ul a:hover,.navbar-body .nav ul a:hover +{background-color:#f5f5f5;} +.bg-black,.border-black .button.active,.pointer.border-black .active,.nav-pills.border-black .active a,.nav-main.border-black .nav-head,.pagination.border-black .active +{background-color:#000;} +.bg-gray,.border-gray .button.active,.pointer.border-gray .active,.nav-pills.border-gray .active a,.nav-main.border-gray .nav-head,.pagination.border-gray .active +{background-color:#999;} +.bg-white,.button.bg,.border-white .button.active,.pointer.border-white .active,.nav-pills.border-white .active a,.nav-main.border-white .nav-head,.pagination.border-white .active +{background-color:#fff;} +.bg-red,.border-red .button.active,.pointer.border-red .active,.nav-pills.border-red .active a,.nav-main.border-red .nav-head,.pagination.border-red .active +{background-color:#e33;} +.bg-yellow,.border-yellow .button.active,.pointer.border-yellow .active,.nav-pills.border-yellow .active a,.nav-main.border-yellow .nav-head,.pagination.border-yellow .active +{background-color:#f60;} +.bg-blue,.border-blue .button.active,.pointer.border-blue active,.nav-pills.border-blue .active a,.nav-main.border-blue .nav-head,.pagination.border-blue .active +{background-color:#0ae;} +.bg-green,.border-green .button.active,.pointer.border-green .active,.nav-pills.border-green .active a,.pagination.border-green .active +{background-color:#2c7;} +.bg-red-light,.table .red, .table .red td, .table .red th,.alert-red,.border-red-light .button.active,.pointer.border-red-light .active,.nav-pills.border-red-light .active a,.nav-main.border-red-light .nav-head,.pagination.border-red-light .active +{background-color:#fee;} +.bg-yellow-light,.table .yellow, .table .yellow td, .table .yellow th,.alert-yellow,.border-yellow-light .button.active,.pointer.border-yellow-light .active,.nav-pills.border-yellow-light .active a,.nav-main.border-yellow-light .nav-head,.pagination.border-yellow-light .active +{background-color:#ffd;} +.bg-blue-light,.table .blue, .table .blue td, .table .blue th,.alert-blue,.border-blue-light .button.active,.pointer.border-blue-light .active,.nav-pills.border-blue-light .active a,.nav-main.border-blue-light .nav-head,.pagination.border-blue-light .active +{background-color:#eff;} +.bg-green-light,.table .green, .table .green td, .table .green th,.alert-green,.border-green-light .button.active,.pointer.border-green-light .active,.nav-pills.border-green-light .active a,.nav-main.border-green-light .nav-head,.pagination.border-green-light .active +{background-color:#efd;} +.border-dashed{border-style:dashed;} +.border-dotted{border-style:dotted;} +.border-double{border-style:double;} +.border-inset{border-style:inset;} +.border-outset{border-style:outset;} +.border-black,.border-black .button,.border-black .tab-nav li a,.border-black .tab-body,.button.bg-black,.selected.border-black,.pointer.border-black li,.nav.border-black .active a,.nav.nav-tabs.border-black,.nav-main.border-black a, .nav-main.border-black .nav-head,.pagination.border-black li,.pager.border-black a +{border-color:#000;} +.border-gray,.border-gray .button,.border-gray .tab-nav li a,.border-gray .tab-body,.button.bg-gray,.selected.border-gray,.pointer.border-gray li,.nav.border-gray .active a,.nav.nav-tabs.border-gray,.nav-main.border-gray a, .nav-main.border-gray .nav-head,.pagination.border-gray li,.pager.border-gray a +{border-color:#999;} +.border-white,.border-white .button,.border-white .tab-nav li a,.border-white .tab-body,.button.bg-white,.selected.border-white,.pointer.border-white li,.nav.border-white .active a,.nav.nav-tabs.border-white,.nav-main.border-white a, .nav-main.border-white .nav-head,.pagination.border-white li,.pager.border-white a +{border-color:#fff;} +.border-red,.border-red .button,.border-red .tab-nav li a,.border-red .tab-body,.button.bg-red,.selected.border-red,.pointer.border-red li,.check-error .input,.nav.border-red .active a,.nav.nav-tabs.border-red,.nav-main.border-red a, .nav-main.border-red .nav-head,.pagination.border-red li,.pager.border-red a +{border-color:#e33;} +.border-yellow,.border-yellow .button,.border-yellow .tab-nav li a,.border-yellow .tab-body,.button.bg-yellow,.selected.border-yellow,.pointer.border-yellow li,.check-warning .input,.nav.border-yellow .active a,.nav.nav-tabs.border-yellow,.nav-main.border-yellow a, .nav-main.border-yellow .nav-head,.pagination.border-yellow li,.pager.border-yellow a +{border-color:#f60;} +.border-blue,.border-blue .button,.border-blue .tab-nav li a,.border-blue .tab-body,.button.bg-blue,.selected.border-blue,.pointer.border-blue li,.nav.border-blue .active a,.nav.nav-tabs.border-blue,.nav-main.border-blue a, .nav-main.border-blue .nav-head,.pagination.border-blue li,.pager.border-blue a +{border-color:#0ae;} +.border-green,.border-green .button,.border-green .tab-nav li a,.border-green .tab-body,.button.bg-green,.selected.border-green,.pointer.border-green li,.check-success .input,.nav.border-green .active a,.nav.nav-tabs.border-green,.nav-main.border-green a, .nav-main.border-green .nav-head,.pagination.border-green li,.pager.border-green a +{border-color:#2c7;} +.border-red-light,.border-red-light .button,.border-red-light .tab-nav li a,.border-red-light .tab-body,.button.bg-red-light,.selected.border-red-light,.alert-red,.pointer.border-red-light li,.nav.border-red-light .active a,.nav.nav-tabs.border-red-light,.nav-main.border-red-light a, .nav-main.border-red-light .nav-head,.pagination.border-red-light li,.pager.border-red-light a +{border-color:#fee;} +.border-yellow-light,.border-yellow-light .button,.border-yellow-light .tab-nav li a,.border-yellow-light .tab-body,.button.bg-yellow-light,.selected.border-yellow-light,.alert-yellow,.pointer.border-yellow-light li,.nav.border-yellow-light .active a,.nav.nav-tabs.border-yellow-light,.nav-main.border-yellow-light a, .nav-main.border-yellow-light .nav-head,.pagination.border-yellow-light li,.pager.border-yellow-light a +{border-color:#ffd;} +.border-blue-light,.border-blue-light .button,.border-blue-light .tab-nav li a,.border-blue-light .tab-body,.button.bg-blue-light,.selected.border-blue-light,.alert-blue,.pointer.border-blue-light li,.nav.border-blue-light .active a,.nav.nav-tabs.border-blue-light,.nav-main.border-blue-light a, .nav-main.border-blue-light .nav-head,.pagination.border-blue-light li,.pager.border-blue-light a +{border-color:#eff;} +.border-green-light,.border-green-light .button,.border-green-light .tab-nav li a,.border-green-light .tab-body,.button.bg-green-light,.selected.border-green-light,.alert-green,.pointer.border-green-light li,.nav.border-green-light .active a,.nav.nav-tabs.border-green-light,.nav-main.border-green-light a, .nav-main.border-green-light .nav-head,.pagination.border-green-light li,.pager.border-green-light a +{border-color:#efd;} +.button:hover,.button:focus,.button.bg:hover,.button.bg:focus{background-color:#f5f5f5;} +.button.border-black:hover,.button.border-black:focus,.button.bg-black:hover,.button.bg-black:focus{color:#fff;border-color:#666;background-color:#666;} +.button.border-gray:hover,.button.border-gray:focus,.button.bg-gray:hover,.button.bg-gray:focus{color:#fff;border-color:#aaa;background-color:#aaa;} +.button.border-white:hover,.button.border-white:focus,.button.bg-white:hover,.button.bg-white:focus{color:#333;border-color:#f5f5f5;background-color:#f5f5f5;} +.button.border-red:hover,.button.border-red:focus,.button.bg-red:hover,.button.bg-red:focus{color:#fff;border-color:#f00;background-color:#f00;} +.button.border-yellow:hover,.button.border-yellow:focus,.button.bg-yellow:hover,.button.bg-yellow:focus{color:#fff;border-color:#f90;background-color:#f90;} +.button.border-blue:hover,.button.border-blue:focus,.button.bg-blue:hover,.button.bg-blue:focus{color:#fff;border-color:#3bd;background-color:#3bd;} +.button.border-green:hover,.button.border-green:focus,.button.bg-green:hover,.button.bg-green:focus{color:#fff;border-color:#5d8;background-color:#5d8;} +.button.border-red-light:hover,.button.border-red-light:focus,.button.bg-red-light:hover,.button.bg-red-light:focus,.alert-red:hover{color:#e33;border-color:#fdc;background-color:#fdc;} +.button.border-yellow-light:hover,.button.border-yellow-light:focus,.button.bg-yellow-light:hover,.button.bg-yellow-light:focus,.alert-yellow:hover{color:#f60;border-color:#fec;background-color:#fec;} +.button.border-blue-light:hover,.button.border-blue-light:focus,.button.bg-blue-light:hover,.button.bg-blue-light:focus,.alert-blue:hover{color:#0ae;border-color:#def;background-color:#def;} +.button.border-green-light:hover,.button.border-green-light:focus,.button.bg-green-light:hover,.button.bg-green-light:focus,.alert-green:hover{color:#2c7;border-color:#cfa;background-color:#cfa;} + + + + +/*--------自定义链接颜色(可选)--------*/ +a{color:#333;text-decoration:none;} /*链接-颜色*/ +a:focus,a:hover{color:#0ae;} /*链接-悬浮颜色*/ +/*--------自定义文本颜色--------*/ +.text-main, a.text-main:link, a.text-main:visited,.button.border-main,blockquote.border-main strong,.pager.border-main a,.pager-prev.border-main,.pager-next.border-main,.nav a:hover,.nav-menu.nav-pills .active ul a:hover,.bg-inverse .nav-menu ul a:hover,.bg-inverse .nav.nav-menu.nav-tabs ul a:hover,.bg-inverse .nav.nav-menu.nav-tabs .active ul a:hover,.bg-inverse .nav.nav-menu.nav-pills ul a:hover,.bg-inverse .nav.nav-menu.nav-pills .active ul a:hover +{color:#0ae;} /*文本-主色*/ +.text-sub, a.text-sub:link, a.text-sub:visited,.button.border-sub,blockquote.border-sub strong,.pager.border-sub a,.pager-prev.border-sub,.pager-next.border-sub +{color:#2c7;} /*文本-辅色*/ +.text-back, a.text-back:link, a.text-back:visited,.button.border-back,blockquote.border-back,.pager.border-back a,.pager-prev.border-back,.pager-next.border-back +{color:#b5cfd9;} /*文本-背景色*/ +.text-mix, a.text-mix:link, a.text-mix:visited,.button.border-mix,blockquote.border-mix,.pager.border-mix a,.pager-prev.border-mix,.pager-next.border-mix +{color:#5cd;}/*文本-融合色*/ +.text-dot, a.text-dot:link, a.text-dot:visited,.button.border-dot,blockquote.border-dot strong,.pager.border-dot a,.pager-prev.border-dot,.pager-next.border-dot +{color:#f60;}/*文本-点缀色*/ +/*--------自定义背景色--------*/ +.bg-main,.border-main .button.active,.pointer.border-main .active,.nav-pills.border-main .active a,.nav-main.border-main .nav-head,.pagination.border-main .active +{background-color:#0ae;} /*背景-主色*/ +.bg-sub,.border-sub .button.active,.pointer.border-sub .active,.nav-pills.border-sub .active a,.nav-main.border-sub .nav-head,.pagination.border-sub .active +{background-color:#2c7;} /*背景-辅色*/ +.bg-back,.border-back .button.active,.pointer.border-back .active,.nav-pills.border-back .active a,.nav-main.border-back .nav-head,.pagination.border-back .active +{background-color:#f2f9fd;} /*背景-背景色*/ +.bg-mix,.border-mix .button.active,.pointer.border-mix .active,.nav-pills.border-mix .active a,.pagination.border-mix .active +{background-color:#5cd;} /*背景-融合色*/ +.bg-dot,.border-dot .button.active,.pointer.border-dot .active,.nav-pills.border-dot .active a,.nav-main.border-dot .nav-head,.pagination.border-dot .active +{background-color:#f60;} /*背景-点缀色*/ +/*--------自定义边框色--------*/ +.border-main,.border-main .button,.border-main .tab-nav li a,.border-main .tab-body,.button.bg-main,.selected.border-main,.pointer.border-main li,.nav.border-main .active a,.nav.nav-tabs.border-main,.nav-main.border-main a, .nav-main.border-main .nav-head,.pagination.border-main li,.pager.border-main a +{border-color:#0ae;} /*边框-主色*/ +.border-sub,.border-sub .button,.border-sub .tab-nav li a,.border-sub .tab-body,.button.bg-sub,.selected.border-sub,.pointer.border-sub li,.nav.border-sub .active a,.nav.nav-tabs.border-sub,.nav-main.border-sub a, .nav-main.border-sub .nav-head,.pagination.border-sub li,.pager.border-sub a +{border-color:#2c7;}/*边框-辅色*/ +.border-back,.border-back .button,.border-back .tab-nav li a,.border-back .tab-body,.button.bg-back,.selected.border-back,.pointer.border-back li,.nav.border-back .active a,.nav.nav-tabs.border-back,.nav-main.border-back a, .nav-main.border-back .nav-head,.pagination.border-back li,.pager.border-back a +{border-color:#b5cfd9;}/*边框-背景色*/ +.border-mix,.border-mix .button,.border-mix .tab-nav li a,.border-mix .tab-body,.button.bg-mix,.selected.border-mix,.pointer.border-mix li,.nav.border-mix .active a,.nav.nav-tabs.border-mix,.nav-main.border-mix a, .nav-main.border-mix .nav-head,.pagination.border-mix li,.pager.border-mix a +{border-color:#5cd;} /*边框-融合色*/ +.border-dot,.border-dot .button,.border-dot .tab-nav li a,.border-dot .tab-body,.button.bg-dot,.selected.border-dot,.pointer.border-dot li,.nav.border-dot .active a,.nav.nav-tabs.border-dot,.nav-main.border-dot a, .nav-main.border-dot .nav-head,.pagination.border-dot li,.pager.border-dot a +{border-color:#f60;} /*边框-点缀色*/ +/*--------自定义按钮悬浮文本、边框及背景色--------*/ +.button.border-main:hover,.button.border-main:focus,.button.bg-main:hover,.button.bg-main:focus +{color:#fff;border-color:#0ae;background-color:#0ae;} /*主色-文本-边框-背景*/ +.button.border-sub:hover,.button.border-sub:focus,.button.bg-sub:hover,.button.bg-sub:focus +{color:#fff;border-color:#b5cfd9;background-color:#b5cfd9;} /*配色-文本-边框-背景*/ +.button.border-back:hover,.button.border-back:focus,.button.bg-back:hover,.button.bg-back:focus +{color:#333;border-color:#def;background-color:#def;} /*背景色-文本-边框-背景*/ +.button.border-mix:hover,.button.border-mix:focus,.button.bg-mix:hover,.button.bg-mix:focus +{color:#333;border-color:#3bc;background-color:#3bc;} /*融合-文本色-边框-背景*/ +.button.border-dot:hover,.button.border-dot:focus,.button.bg-dot:hover,.button.bg-dot:focus +{color:#fff;border-color:#f00;background-color:#f00;} /*点缀色-文本-边框-背景*/ \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataInfo.html b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataInfo.html new file mode 100644 index 0000000..3f023b6 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataInfo.html @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + +
+
 包内简介(package-info.java)
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataList.html b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataList.html new file mode 100644 index 0000000..b64b5ce --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/dataList.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + +
+
+
 类文件列表(*.java)
+ + + + + + + + + + + <#list classList as classData> + + + + + + + + + + + + + +
序号类文件名类名简介作者版本功能描述创建时间
${classData_index}${classData.apiTypeName!'未解析出'}${classData.apiTypeName!'未解析出'}${classData.author!'未解析出'}${classData.version!'未解析出'}${classData.apiDescription!'未解析出'}${classData.date!'未解析出'}
+
+ + <#list pageIndexList as indexNo> + ${indexNo} + +
+
+
+
+ + \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/bg.jpg b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..06ae58bec0edda6738098a2cb68cd2a195cf2fa3 GIT binary patch literal 103501 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 C)Q^_{ literal 0 HcmV?d00001 diff --git a/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/tmbg-white.png b/coffice-toolbox-apidoc/src/main/resources/META-INF/resources/apidoc/images/tmbg-white.png new file mode 100644 index 0000000000000000000000000000000000000000..c809ca34d06d5a69f95a4f8ecd8be5e10ccca627 GIT binary patch literal 1012 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 literal 0 HcmV?d00001 diff --git a/coffice-toolbox-apidoc/src/main/resources/apache2.0.license b/coffice-toolbox-apidoc/src/main/resources/apache2.0.license new file mode 100644 index 0000000..29cee2c --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/apache2.0.license @@ -0,0 +1,17 @@ + /* + * Copyright (c) 2019, LIBO/alex All rights reserved. + * + * http://blog.sina.com.cn/alex4java + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/main/resources/apidoc.properties b/coffice-toolbox-apidoc/src/main/resources/apidoc.properties new file mode 100644 index 0000000..e5dd5a9 --- /dev/null +++ b/coffice-toolbox-apidoc/src/main/resources/apidoc.properties @@ -0,0 +1 @@ +api.scan.package=com.hyts \ No newline at end of file diff --git a/coffice-toolbox-apidoc/src/test/java/TODO b/coffice-toolbox-apidoc/src/test/java/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestParser.java b/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestParser.java new file mode 100644 index 0000000..727307a --- /dev/null +++ b/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestParser.java @@ -0,0 +1,39 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.test; +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.parser.JavaDocApiParser; + +/** + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月23日 + * @version V1.0 + */ +public class TestParser { + /** + * @param args + * @exception 热爱奥所多 + */ + public static void main(String[] args) { + ScanBaseObject scanBaseObject = new ScanBaseObject(); + scanBaseObject.packages = new String[] {"com.hyts.apidoc"}; + new JavaDocApiParser().execute(scanBaseObject).forEach(param->{ + System.out.println(param); + }); + } +} diff --git a/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestScanner.java b/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestScanner.java new file mode 100644 index 0000000..8d5b147 --- /dev/null +++ b/coffice-toolbox-apidoc/src/test/java/com/hyts/apidoc/test/TestScanner.java @@ -0,0 +1,40 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.apidoc.test; + +import com.hyts.apidoc.bean.ScanBaseObject; +import com.hyts.apidoc.parser.JavaDocApiParser; + +/** + * @author LiBo/Alex + * @see TODO制定另外一个主体的链接 + * @since TODO引入特定改变发布版本 + * @version V1.0 + */ +public class TestScanner { + + /** + * @param args + * @exception 热爱奥所多 + */ + public static void main(String[] args) { + ScanBaseObject scanBaseObject = new ScanBaseObject(); + scanBaseObject.packages = new String[] {"com.hyts.apidoc"}; + new JavaDocApiParser().execute(scanBaseObject).forEach(param->{ + System.out.println(param); + }); + } + +} diff --git a/coffice-toolbox-apidoc/src/test/resources/TODO b/coffice-toolbox-apidoc/src/test/resources/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-aspect/pom.xml b/coffice-toolbox-aspect/pom.xml new file mode 100644 index 0000000..7527ab3 --- /dev/null +++ b/coffice-toolbox-aspect/pom.xml @@ -0,0 +1,119 @@ + + 4.0.0 + + com.hyts + coffice-toolbox + 1.0.0 + + coffice-toolbox-aspect + + + UTF-8 + 1.2.17 + 2.3 + 1.8 + 4.12 + 3.2.5 + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + + + alex4java + alexTheWorld + http://www.libo2018.cn + + developer + + + + + + + junit + junit + ${junit.version} + test + + + + cglib + cglib + ${cglib.version} + + + com.hyts + coffice-toolbox-scanner + 1.0.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + ${jdk.version} + ${jdk.version} + ${project.build.sourceEncoding} + + + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + release + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + + + + \ No newline at end of file diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/AopProxy.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/AopProxy.java new file mode 100644 index 0000000..d4cf9c5 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/AopProxy.java @@ -0,0 +1,124 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop; + +import java.util.concurrent.atomic.AtomicBoolean; + +import com.hyts.aop.error.AopException; +import com.hyts.aop.handler.cglib.CglibAopHandler; +import com.hyts.aop.proxy.AopContext; +import com.hyts.aop.proxy.ProxyBuilder; + +/** + * @title AopExecutor.java + * @package com.hyts.aop + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public final class AopProxy { + + /** + * @fieldName isInit + * @fieldType AtomicBoolean + */ + private static AtomicBoolean isInit = new AtomicBoolean(false); + + private static AopContext globalAopContext = null; + + /** + * executeJdkAopBean + *

执行AOP面向切面变成开发操作

+ * @param object 参数传递 + * @return 返回 + * @exception + */ + @SuppressWarnings("unchecked") + public static V executeJdkAopBean(T object,Class interfaceClass) { + return (V) new ProxyBuilder(object).build(interfaceClass); + } + + /** + * executeJdkAopBean + *

执行AOP面向切面变成开发操作

+ * @param object 参数传递 + * @return 返回 + * @exception + */ + @SuppressWarnings("unchecked") + public static V executeJdkAopBean(T object,Object aopWeaveObj,Class interfaceClass) { + return (V) new ProxyBuilder(object,aopWeaveObj).build(interfaceClass); + } + + /** + * executeJdkAopObject + *

执行AOP面向切面变成开发操作

+ * @param object + * @return + * @exception + */ + public static Object executeJdkAopObject(Object object) { + return new ProxyBuilder(object).build(); + } + + /** + * executeCglibAopBean + *

执行AOP面向切面变成开发操作

+ * @param object 参数传递 + * @return 返回 + * @exception + */ + @SuppressWarnings("unchecked") + public static T executeCglibAopBean(T object) { + return (T) new ProxyBuilder(new CglibAopHandler(object),object).build(object.getClass()); + } + + /** + * executeCglibAopObject + *

执行AOP面向切面变成开发操作

+ * @param object + * @return + * @exception + */ + public static Object executeCglibAopObject(Object object) { + return new ProxyBuilder(new CglibAopHandler(object)).build(); + } + + /** + * @param clazz + * @return + * @exception + */ + public static T getCallerProxy(Class clazz){ + //全局AOPContext上下文 + if(globalAopContext == null) { + throw new AopException("没有初始化AopContext上下文,请调用initAopContext方法"); + } + return AopContext.getInvokeProxyObject(clazz); + } + + /** + * @param backPackage + * @exception + */ + public static void initAopContext(String backPackage) { + if(isInit.compareAndSet(false, true)) { + globalAopContext = new AopContext(backPackage); + globalAopContext.init(); + } + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/BaseAopHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/BaseAopHandler.java new file mode 100644 index 0000000..979370a --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/BaseAopHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.base; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import com.hyts.aop.annotation.Before; +import com.hyts.aop.annotation.Pointcut; +import com.hyts.aop.error.AopException; + +/** + * @title AopHandler.java + * @package com.hyts.aop.handler + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月24日 + * @version V1.0 + */ +public abstract class BaseAopHandler { + + /** + *

代理操作的原生对象

+ * @fieldName proxyRealObject + * @fieldType Object + */ + private Object proxyRealObject; + + /** + *

{字段的描述}

+ * @fieldName aopWeaveObject + * @fieldType Object + */ + protected Object aopWeaveObject; + + /** + * @constructor:BaseAopHandler + * @param proxyRealObject + */ + public BaseAopHandler(Object proxyRealObject) { + super(); + this.proxyRealObject = proxyRealObject; + } + + /** + * @name proxyRealObject's getter method + * @param none + * @return proxyRealObject + */ + public Object getProxyRealObject() { + return proxyRealObject; + } + + /** + * @param obj + * @exception + */ + public void settingsAopWeaveObj(Object obj) { + this.aopWeaveObject = obj; + } + + public abstract T build(T clazz) throws AopException; + + public abstract Object build() throws AopException; +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/package-info.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/package-info.java new file mode 100644 index 0000000..edb2e30 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/base/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author LiBo/Alex + * @see TODO制定另外一个主体的链接 + * @since TODO引入特定改变发布版本 + * @version V1.0 + */ +package com.hyts.aop.base; \ No newline at end of file diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/error/AopException.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/error/AopException.java new file mode 100644 index 0000000..46e2bfb --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/error/AopException.java @@ -0,0 +1,69 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.error; + +/** + * @author LiBo/Alex + * @see java.lang.RuntimeException + * @since 1.0 + * @version V1.0 + */ +public class AopException extends RuntimeException { + + /** + * @fieldName serialVersionUID + * @fieldType long + */ + private static final long serialVersionUID = 6686247375172461933L; + + /** + * @constructor:AopException + */ + public AopException() { + super(); + } + + /** + * @constructor:AopException + * @param message + * @param cause + */ + + + public AopException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @constructor:AopException + * @param message + */ + + + public AopException(String message) { + super(message); + } + + /** + * @constructor:AopException + * @param cause + */ + + + public AopException(Throwable cause) { + super(cause); + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/CglibAopHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/CglibAopHandler.java new file mode 100644 index 0000000..4823e25 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/CglibAopHandler.java @@ -0,0 +1,82 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.handler.cglib; + +import com.hyts.aop.base.BaseAopHandler; +import com.hyts.aop.error.AopException; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.Enhancer; + +/** + * @author LiBo/Alex + * @see com.hyts.aop.base.BaseAopHandler + * @since V1.0 + * @version V1.0 + */ +public class CglibAopHandler extends BaseAopHandler { + + /** + * @fieldName enhancer + * @fieldType Enhancer + */ + private final Enhancer enhancer; + + /** + * @constructor:CglibAopHandler + * @param proxyRealObject + */ + public CglibAopHandler(Object proxyRealObject) { + super(proxyRealObject); + enhancer = new Enhancer(); + enhancer.setSuperclass(proxyRealObject.getClass()); + enhancer.setCallback(new MethodInterceptorHandler(proxyRealObject)); + } + + /** + * @name enhancer's getter method + * @param none + * @return enhancer + */ + public Enhancer getEnhancer() { + return enhancer; + } + + /* + * @param clazz + * @return + * @throws AopException + * @see com.hyts.aop.base.BaseAopHandler#build(java.lang.Object) + * @exception + */ + @SuppressWarnings("unchecked") + @Override + public T build(T clazz) throws AopException { + return (T) enhancer.create(); + } + + /* + * @return + * @throws AopException + * @see com.hyts.aop.base.BaseAopHandler#build() + * @exception + */ + @Override + public Object build() throws AopException { + return enhancer.create(); + } + + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/MethodInterceptorHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/MethodInterceptorHandler.java new file mode 100644 index 0000000..b9afdfb --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/cglib/MethodInterceptorHandler.java @@ -0,0 +1,98 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.handler.cglib; + +import java.lang.reflect.Method; +import java.util.logging.Logger; + +import com.hyts.aop.handler.common.AfterMethodHandler; +import com.hyts.aop.handler.common.BeforeMethodHandler; +import com.hyts.aop.handler.common.PointcutMethodHandler; +import com.hyts.aop.handler.common.RoundMethodHandler; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * @author LiBo/Alex + * @see net.sf.cglib.proxy.MethodInterceptor + * @since V1.0 + * @version V1.0 + */ +public class MethodInterceptorHandler implements MethodInterceptor { + + private final BeforeMethodHandler beforeMethodHandler; + + private final AfterMethodHandler afterMethodHandler; + + private final RoundMethodHandler roundMethodHandler; + + private final PointcutMethodHandler pointcutMethodHandler; + + /** + * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(BeforeMethodHandler.class.getName()); + + /** + * @constructor:BeforeAopHandler + * @param proxyRealObject + */ + public MethodInterceptorHandler(Object proxyRealObject) { + beforeMethodHandler = new BeforeMethodHandler(proxyRealObject); + afterMethodHandler = new AfterMethodHandler(proxyRealObject); + roundMethodHandler = new RoundMethodHandler(proxyRealObject); + pointcutMethodHandler = new PointcutMethodHandler(proxyRealObject); + } + + /** + * @constructor:BeforeAopHandler + * @param proxyRealObject + */ + public MethodInterceptorHandler(Object proxyRealObject,Object weaveObject) { + beforeMethodHandler = new BeforeMethodHandler(weaveObject); + afterMethodHandler = new AfterMethodHandler(weaveObject); + roundMethodHandler = new RoundMethodHandler(weaveObject); + pointcutMethodHandler = new PointcutMethodHandler(proxyRealObject); + } + + /* + * @param obj + * @param method + * @param args + * @param proxy + * @return + * @throws Throwable + * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy) + * @exception + */ + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + //校验是否被选中为忽略状态 + Object result = null; + if(pointcutMethodHandler.validate(method)) { + beforeMethodHandler.before(); + roundMethodHandler.round(); + } + result = proxy.invokeSuper(obj, args); + if(pointcutMethodHandler.validate(method)) { + roundMethodHandler.round(); + afterMethodHandler.after(); + } + return result; + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/AfterMethodHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/AfterMethodHandler.java new file mode 100644 index 0000000..6aeaff0 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/AfterMethodHandler.java @@ -0,0 +1,71 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.handler.common; + +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Logger; + +import com.hyts.aop.annotation.After; +import com.hyts.aop.annotation.Ignore; + +/** + * @title OriginalAopHandler.java + * @package com.hyts.aop.handler.java + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public class AfterMethodHandler { + + /** + *

+ * {字段的描述} + *

+ * + * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(AfterMethodHandler.class.getName()); + + + private Object proxyRealObject; + + /** + * @constructor:BeforeMethodHandler + * @param methods + * @param proxyRealObject + */ + public AfterMethodHandler(Object proxyRealObject) { + this.proxyRealObject = proxyRealObject; + } + + /** + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + * @exception + */ + public void after() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for(int i = 0 ; i + * {字段的描述} + *

+ * + * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(BeforeMethodHandler.class.getName()); + + + private Method[] methods; + + private Object proxyRealObject; + + /** + * @constructor:BeforeMethodHandler + * @param methods + * @param proxyRealObject + */ + public BeforeMethodHandler(Object proxyRealObject) { + super(); + this.methods = proxyRealObject.getClass().getMethods(); + this.proxyRealObject = proxyRealObject; + } + + /** + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + * @exception + */ + public void before() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for(int i = 0 ; i + * {字段的描述} + *

+ * + * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(PointcutMethodHandler.class.getName()); + + private Method[] methods; + + private Object proxyRealObject; + + /** + * @constructor:BeforeMethodHandler + * @param methods + * @param proxyRealObject + */ + public PointcutMethodHandler(Object proxyRealObject) { + this.methods = proxyRealObject.getClass().getMethods(); + this.proxyRealObject = proxyRealObject; + } + + /** + * IllegalAccessException @throws IllegalArgumentException @throws + * InvocationTargetException @exception + */ + public boolean validate(Method method) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for (int i = 0; i < methods.length; i++) { + if (method.getName().equals(methods[i].getName())) { + if (!methods[i].isAnnotationPresent(Ignore.class)) { + return true; + } + } + } + return false; + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/RoundMethodHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/RoundMethodHandler.java new file mode 100644 index 0000000..782e6a6 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/common/RoundMethodHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.handler.common; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.logging.Logger; + +import com.hyts.aop.annotation.After; +import com.hyts.aop.annotation.Ignore; +import com.hyts.aop.annotation.Round; + +/** + * @title RoundAopHandler.java + * @package com.hyts.aop.handler.java + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public class RoundMethodHandler { + + /** + *

+ * {字段的描述} + *

+ * + * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(RoundMethodHandler.class.getName()); + + + private Method[] methods; + + private Object proxyRealObject; + + /** + * @constructor:BeforeMethodHandler + * @param methods + * @param proxyRealObject + */ + public RoundMethodHandler(Object proxyRealObject) { + this.methods = proxyRealObject.getClass().getMethods(); + this.proxyRealObject = proxyRealObject; + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + * @exception + */ + public void round() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for(int i = 0 ; i + * {字段的描述} + *

+ * @fieldName logger + * @fieldType Logger + */ + Logger logger = Logger.getLogger(BeforeMethodHandler.class.getName()); + + /** + * @constructor:BeforeAopHandler + * @param proxyRealObject + */ + public DefaultAopHandler(Object proxyRealObject) { + super(proxyRealObject); + aopWeaveObject = proxyRealObject; + beforeMethodHandler = new BeforeMethodHandler(aopWeaveObject); + afterMethodHandler = new AfterMethodHandler(aopWeaveObject); + roundMethodHandler = new RoundMethodHandler(aopWeaveObject); + pointcutMethodHandler = new PointcutMethodHandler(aopWeaveObject); + } + + /** + * @constructor:DefaultAopHandler + * @param proxyRealObject + * @param aopWeaveObject + */ + public DefaultAopHandler(Object proxyRealObject,Object aopWeaveObject) { + super(proxyRealObject); + beforeMethodHandler = new BeforeMethodHandler(aopWeaveObject); + afterMethodHandler = new AfterMethodHandler(aopWeaveObject); + roundMethodHandler = new RoundMethodHandler(aopWeaveObject); + pointcutMethodHandler = new PointcutMethodHandler(proxyRealObject); + } + + + /* + * @param proxy + * @param method + * @param args + * @return + * @throws Throwable + * @see com.hyts.aop.handler.BaseAopHandler#invoke(java.lang.Object, + * java.lang.reflect.Method, java.lang.Object[]) + * @exception + */ + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + //校验是否被选中为忽略状态 + Object result = null; + if(pointcutMethodHandler.validate(method) ) { + beforeMethodHandler.before(); + roundMethodHandler.round(); + } + //if(pointcutMethodHandler.validate(method)) { + result = method.invoke(this.getProxyRealObject(), args); + //} + if(pointcutMethodHandler.validate(method)) { + roundMethodHandler.round(); + afterMethodHandler.after(); + } + return result; + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/java/JdkAopHandler.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/java/JdkAopHandler.java new file mode 100644 index 0000000..164d50e --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/handler/java/JdkAopHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.handler.java; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import com.hyts.aop.annotation.Before; +import com.hyts.aop.annotation.Pointcut; +import com.hyts.aop.base.BaseAopHandler; +import com.hyts.aop.error.AopException; + +/** + * @title JdkAopHandler.java + * @package com.hyts.aop.handler + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月24日 + * @version V1.0 + */ +public class JdkAopHandler extends BaseAopHandler implements InvocationHandler { + + + /** + * @constructor:BaseAopHandler + * @param proxyRealObject + */ + public JdkAopHandler(Object proxyRealObject) { + super(proxyRealObject); + } + /** + * execute:主要用于操作执行的方法 + *

开发者无需管理系统的java proxy管理的invoke方法,只需要覆盖此方法即可

+ * @param param 输入参数 + * @return + * @exception + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return method.invoke(getProxyRealObject(),args); + } + + /** + * @param clazz + * @return + * @throws InstantiationException + * @throws IllegalAccessException + * @exception + */ + @SuppressWarnings("unchecked") + public T build(T clazz) throws AopException{ + return (T)Proxy.newProxyInstance(getProxyRealObject().getClass().getClassLoader(),getProxyRealObject().getClass().getInterfaces(),this); + } + + /** + * @return + * @throws InstantiationException + * @throws IllegalAccessException + * @exception + */ + public Object build() throws AopException { + return Proxy.newProxyInstance(getProxyRealObject().getClass().getClassLoader(),getProxyRealObject().getClass().getInterfaces(),this); + } + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/plugins/ThirdPartyPlugins.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/plugins/ThirdPartyPlugins.java new file mode 100644 index 0000000..cd92385 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/plugins/ThirdPartyPlugins.java @@ -0,0 +1,29 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.plugins; + +/** + * @title ThirdPartyPlugins.java + * @package com.hyts.aop.plugins + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public class ThirdPartyPlugins { + +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanAop.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanAop.java new file mode 100644 index 0000000..a789f31 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanAop.java @@ -0,0 +1,42 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.pointcut; + +import java.util.List; + +import com.hyts.aop.annotation.AopContext; +import com.hyts.scanner.bean.ScanBaseObject; +import com.hyts.scanner.core.SourceAndJarHandler; + +/** + * @title AopInterface.java + * @package com.hyts.aop.pointcut + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public class ScanAop { + + /** + * @exception + */ + public static List> scanAop(String[] packageNames) { + ScanBaseObject scanBaseObject = new ScanBaseObject(); + scanBaseObject.annotations = new Class[] {AopContext.class}; + scanBaseObject.packages = packageNames; + return new SourceAndJarHandler(true).scan(scanBaseObject).scanResultClass; + } +} diff --git a/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanPointcut.java b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanPointcut.java new file mode 100644 index 0000000..3289834 --- /dev/null +++ b/coffice-toolbox-aspect/src/main/java/com/hyts/aop/pointcut/ScanPointcut.java @@ -0,0 +1,52 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.pointcut; + +import java.util.List; + +import com.hyts.aop.annotation.AopContext; +import com.hyts.aop.annotation.Aspect; +import com.hyts.aop.annotation.Pointcut; +import com.hyts.aop.annotation.Weave; +/*import com.hyts.scanner.bean.ScanBaseObject; +import com.hyts.scanner.core.Scanner; +import com.hyts.scanner.core.SourceScanner;*/ +import com.hyts.scanner.bean.ScanBaseObject; +import com.hyts.scanner.core.Scanner; +import com.hyts.scanner.core.SourceAndJarHandler; + +/** + * @title ScanPointcut.java + * @package com.hyts.aop.pointcut + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public final class ScanPointcut { + + /** + * @exception + */ + public static List> scanAspect(String[] packageNames) { + ScanBaseObject scanBaseObject = new ScanBaseObject(); + scanBaseObject.annotations = new Class[] {Aspect.class,Weave.class}; + scanBaseObject.packages = packageNames; + return new SourceAndJarHandler(true).scan(scanBaseObject).scanResultClass; + } + + + +} diff --git a/coffice-toolbox-aspect/src/main/resources/TODO b/coffice-toolbox-aspect/src/main/resources/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-aspect/src/test/java/TODO b/coffice-toolbox-aspect/src/test/java/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/DI.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/DI.java new file mode 100644 index 0000000..7a3b2bc --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/DI.java @@ -0,0 +1,47 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test; + +import com.hyts.aop.annotation.AopContext; +import com.hyts.aop.annotation.Inject; +import com.hyts.aop.test.cglib.AopSuperClass; +import com.hyts.aop.test.jdk.AopInterface; + +/** + * @title TestInjectService.java + * @package com.hyts.aop.test + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月26日 + * @version V1.0 + */ +@AopContext +public class DI { + + @Inject + private AopInterface aop; + + @Inject + private AopSuperClass aop2; + + public void jdk() { + aop.execute(); + aop.execute1(); + } + + public void cglib() { + aop2.test(); + } +} diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/TestDemo.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/TestDemo.java new file mode 100644 index 0000000..931a2c1 --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/TestDemo.java @@ -0,0 +1,46 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test; + +import com.hyts.aop.AopProxy; +import com.hyts.aop.proxy.AopContext; +import com.hyts.aop.test.cglib.AopSuperClass; +import com.hyts.aop.test.jdk.AopInterface; +import com.hyts.aop.test.jdk.AopInterfaceImpl; + +/** + * @author LiBo/Alex + * @see TODO制定另外一个主体的链接 + * @since TODO引入特定改变发布版本 + * @version V1.0 + */ +public class TestDemo { + + + /** + * @exception + */ + public static void testAop() { + AopProxy.initAopContext("com.hyts"); + DI defined = AopProxy.getCallerProxy(DI.class); + defined.jdk(); + defined.cglib(); + } + + + public static void main(String[] args) { + testAop(); + } +} diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/WeaveDemo.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/WeaveDemo.java new file mode 100644 index 0000000..5fe4eab --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/WeaveDemo.java @@ -0,0 +1,46 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test; + +import com.hyts.aop.annotation.After; +import com.hyts.aop.annotation.Aspect; +import com.hyts.aop.annotation.Before; +import com.hyts.aop.annotation.Round; +import com.hyts.aop.annotation.Weave; + +/** + * @author LiBo/Alex + * @see TODO制定另外一个主体的链接 + * @since TODO引入特定改变发布版本 + * @version V1.0 + */ +@Weave +public class WeaveDemo { + + //@Round + public void roundMethod() { + System.out.println("roundMethod"); + } + + @Before + public void beforeMethod() { + System.out.println("beforeMethod"); + } + + @After + public void afterMethod() { + System.out.println("afterMethod"); + } +} diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/cglib/AopSuperClass.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/cglib/AopSuperClass.java new file mode 100644 index 0000000..aa44706 --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/cglib/AopSuperClass.java @@ -0,0 +1,33 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test.cglib; + +import com.hyts.aop.annotation.Aspect; +import com.hyts.aop.annotation.Pointcut; + +/** + * @author LiBo/Alex + * @see TODO制定另外一个主体的链接 + * @since TODO引入特定改变发布版本 + * @version V1.0 + */ +@Aspect +public class AopSuperClass { + + public void test() { + System.out.println("testSuper"); + } + +} diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterface.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterface.java new file mode 100644 index 0000000..ad92e81 --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterface.java @@ -0,0 +1,35 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test.jdk; + +import com.hyts.aop.annotation.After; +import com.hyts.aop.annotation.Before; +import com.hyts.aop.annotation.Ignore; +import com.hyts.aop.pointcut.ScanAop; + +/** + * @title AopInterface.java + * @package com.hyts.aop.pointcut + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +public interface AopInterface { + + void execute(); + void execute1(); + +} diff --git a/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterfaceImpl.java b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterfaceImpl.java new file mode 100644 index 0000000..770322f --- /dev/null +++ b/coffice-toolbox-aspect/src/test/java/com/hyts/aop/test/jdk/AopInterfaceImpl.java @@ -0,0 +1,40 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.aop.test.jdk; + +import com.hyts.aop.annotation.Aspect; +import com.hyts.aop.annotation.Ignore; + +/** + * @title TestInterfaceImpl.java + * @package com.hyts.aop.test + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月25日 + * @version V1.0 + */ +@Aspect +public class AopInterfaceImpl implements AopInterface { + + //@Ignore + public void execute() { + System.out.println(this.getClass().getName()); + } + + //@Ignore + public void execute1() { + System.out.println(this.getClass().getName()+"execute1"); + } +} diff --git a/coffice-toolbox-aspect/src/test/resources/TODO b/coffice-toolbox-aspect/src/test/resources/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-binder/pom.xml b/coffice-toolbox-binder/pom.xml new file mode 100644 index 0000000..b9b22b4 --- /dev/null +++ b/coffice-toolbox-binder/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + + com.hyts + coffice-toolbox + 1.0.0 + + coffice-toolbox-binder + + + UTF-8 + UTF-8 + + UTF-8 + 3.6.0 + + 1.8 + 4.11 + + 4.0 + 1 + 1.0 + 2.6 + + + + javax.inject + javax.inject + ${java.inject.version} + + + com.google.inject + guice + ${guice.version} + + + aopalliance + aopalliance + ${aopalliance.version} + + + + junit + junit + ${junit.version} + test + + + commons-lang + commons-lang + ${apache.commons.lang.version} + + + com.google.inject.extensions + guice-multibindings + ${guice.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + true + ${jdk.version} + ${jdk.version} + ${project.build.sourceEncoding} + + + + + \ No newline at end of file diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseBinder.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseBinder.java new file mode 100644 index 0000000..c801d8a --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseBinder.java @@ -0,0 +1,84 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.base; + +import com.google.inject.AbstractModule; +import com.google.inject.Binder; +import com.hyts.bind.domain.BindDomains; + +/** + * @Title BaseBindere.java + * @Package com.hyts.bind.base + * @Description + *

+ * 基础绑定操作类,用于绑定接口以及服务, + * 提供系统服务统一接口绑定操作服务, + * 此插件暂时只用于单机本地版,稍后会提供。 + * 扫描分模型模块操作 + *

+ * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public abstract class BaseBinder extends AbstractModule{ + + /** + * @Fields field:field:{todo}构建全局所有bind底层Guice对象 + */ + protected Binder bind ; + + /** + * @Fields field:field:{todo} 私有变量定义域 + */ + private BindDomains domains; + + /** + * @param paramtheparamthe{bare_field_name} to set + */ + public void setDomains(BindDomains domains) { + this.domains = domains; + } + + /** + * @Title: initBinder + * @Description: 构建绑定方法的操作构造器 + * @param @param domains + * @param @return 参数 + * @return boolean 返回类型 + * @throws + */ + public abstract boolean initBinder(BindDomains domains); + + /* (非 Javadoc) + *

Title: configure

+ *

Description:

+ * @see com.google.inject.AbstractModule#configure() + */ + @Override + protected void configure() { + if(domains != null) + this.initBinder(domains); + } + + /** + * @return bind + */ + public Binder getBind() { + if(bind == null) + bind = binder(); + return bind; + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseGuiceHandler.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseGuiceHandler.java new file mode 100644 index 0000000..af8d26f --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseGuiceHandler.java @@ -0,0 +1,45 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.base; + +/** + * @Title BaseGuiceHandler.java + * @Package com.hyts.bind.base + * @Description 基础依赖注入操作Guice句柄服务处理器 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public abstract class BaseGuiceHandler { + + /** + * @Title: bindClass + * @Description: 普通绑定:接口-接口实现类操作服务 + * @param @param domain 参数 + * @return void 返回类型 + * @throws + */ + public abstract void bindClass(T domain); + + /** + * @Title: bindProvider + * @Description: 普通绑定:接口-接口实现类操作服务(获取Provider对象的引用对象) + * @param @param domain 参数 + * @return void 返回类型 + * @throws + */ + public abstract void bindProvider(T domain); + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseInjector.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseInjector.java new file mode 100644 index 0000000..a60db42 --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/base/BaseInjector.java @@ -0,0 +1,135 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.base; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.hyts.bind.binder.DefaultClassBinder; +import com.hyts.bind.domain.BindDomains; +import com.hyts.bind.error.GuiceBindException; + +/** + * @Title BaseInjector.java + * @Package com.hyts.bind.base + * @Description + *

+ * 系统基础操作服务,依赖注入器 用于主要操作获取绑定所有注入操作的核心对象类 + *

+ * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public abstract class BaseInjector { + + /** + * @Fields field:field:依赖注入器 + */ + private static Injector injector; + + /** + * @Fields field:field:{todo}绑定域名称集合,系统自带默认 + */ + protected static BindDomains defaultBindDomains; + + /** + * @Fields field:field:依赖注入的所有模型对象集合 + */ + private static List moduleSubjectList; + + /** + * @Fields field:field:{todo}是否启动 + */ + private static AtomicBoolean isInit = new AtomicBoolean(false); + + /** + * @return moduleSubjectList 获取所有依赖注入绑定模型对象 + */ + public static List getModuleSubjectList() { + return moduleSubjectList; + } + + /** + * @fieldName binder + * @fieldType BaseBinder + */ + private static BaseBinder binder; + + /** + * @Title: init @Description: 构建初始化所有模型依赖注入绑定对象,默认会自动加载BaseBinder的对象中的 + * 依赖注入绑定关系 @param @return 参数 @return boolean 返回类型 @throws + */ + public static boolean init() { + if (isInit.get()) + throw new GuiceBindException("系统状态已经启动!"); + moduleSubjectList = new LinkedList(); + // if(getModuleSubjectList() != null && getModuleSubjectList().size() != 0) + // { + // 注册系统默认的操作服务 + binder = new DefaultClassBinder(); + binder.setDomains(defaultBindDomains); + registerInjector(binder); + injector = Guice.createInjector(moduleSubjectList); + isInit = new AtomicBoolean(true); + // } + return false; + } + + /** + * @Title: registerInjector @Description: 向架构注册用户自定义的依赖注入模型(抛出异常) @param @return + * 返回是否成功或者失败 @return boolean 返回类型 @throws + */ + protected static boolean registerInjector(T module) { + if (module != null && module instanceof AbstractModule) { + getModuleSubjectList().add((AbstractModule) module); + return true; + } else + throw new GuiceBindException("传入的注册依赖注入模型对象为空 或者没有实现AbstractModule接口"); + } + + /** + * @Title: registerInjector @Description: 向架构注册用户自定义的依赖注入模型 @param @param + * module @param @param ingoreError @param @return 参数 @return boolean + * 返回类型 @throws + */ + public static boolean registerInjector(T module, boolean ingoreError) { + if (module != null && module instanceof AbstractModule) { + getModuleSubjectList().add((AbstractModule) module); + return true; + } else { + if (ingoreError) { + return false; + } else { + throw new GuiceBindException("传入的注册依赖注入模型对象为空 或者没有实现AbstractModule接口"); + } + } + } + + /** + * @Title: getInjector @Description: 获取Injector依赖注入的控制器 @param @return + * 参数 @return Injector 返回类型 @throws + */ + public Injector getInjector() { + return injector; + } + + public static BaseBinder getBinder() { + return binder; + } +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/BinderService.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/BinderService.java new file mode 100644 index 0000000..b108406 --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/BinderService.java @@ -0,0 +1,32 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.binder; + + +/** + * @Title BinderService.java + * @Package com.hyts.bind.binder + * @Description TODO(用一句话描述该文件做什么) + * @author LiBo/Alex + * @date 2018年4月13日 + * @version V1.0 + */ +public interface BinderService { + + public default void preBind(){ + //injector.getInjector().getInstance(TestService.class); + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/DefaultClassBinder.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/DefaultClassBinder.java new file mode 100644 index 0000000..9f2311a --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/binder/DefaultClassBinder.java @@ -0,0 +1,65 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.binder; + +import java.util.Iterator; + +import com.google.inject.Binder; +import com.google.inject.Scopes; +import com.hyts.bind.base.BaseBinder; +import com.hyts.bind.domain.BindDomain; +import com.hyts.bind.domain.BindDomains; +import com.hyts.bind.handler.DefaultBindHandler; + +/** + * @Title DefaultClassBinder.java + * @Package com.hyts.bind.binder + * @Description 默认操作级别的class类绑定操作服务类 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class DefaultClassBinder extends BaseBinder{ + + /** + * @Fields field:field:{todo}绑定操作处理器操作组件 + */ + private DefaultBindHandler handler; + + /* (非 Javadoc) + *

Title: initBinder

+ *

Description:

+ * @param domains + * @return + * @see com.hyts.bind.base.BaseBinder#initBinder(com.hyts.bind.domain.BindDomains) + */ + @Override + public boolean initBinder(BindDomains domains) { + + if(domains.getBindDomains() == null ) { + return false; + } + Iterator iterator = domains.getBindDomains().iterator(); + //启动默认操作绑定服务 + handler = new DefaultBindHandler(this.getBind()); + while(iterator.hasNext()) { + BindDomain domain = iterator.next(); + handler.bindClass(domain); + } + return true; + } + + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/domain/BindDomains.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/domain/BindDomains.java new file mode 100644 index 0000000..aa93dfd --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/domain/BindDomains.java @@ -0,0 +1,165 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.domain; + +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +import org.apache.commons.lang.StringUtils; + +/** + * @Title BindDomains.java + * @Package com.hyts.bind.domain + * @Description bind绑定对象信息集合 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class BindDomains { + + /** + * @Fields field:field:{todo}绑定域对象集合信息 + */ + private List bindDomains; + + /** + * 创建一个新的实例-构造器 BindDomains. + * @param bindDomains + */ + public BindDomains(List bindDomains) { + super(); + this.bindDomains = bindDomains; + } + + /** + * 创建一个新的实例-构造器 BindDomains. + */ + public BindDomains() { + super(); + this.bindDomains = new LinkedList(); + } + + /** + * 创建一个新的实例-构造器 BindDomains. + * @param interfaceClass + * @param implementClass + */ + public BindDomains(Class interfaceClass,Class implementClass) { + this.bindDomains = new LinkedList(); + addBindSubject(interfaceClass,implementClass); + } + + /** + * @return bindDomains + */ + public List getBindDomains() { + return bindDomains; + } + + /** + * @Title: addBindSubject + * @Description: 构建服务绑定对象快捷方法 + * @param @param interfaceClass + * @param @param implementClass + * @param @return + * @param @throws ClassNotFoundException 参数 + * @return boolean 返回类型 + * @throws + */ + public BindDomains addBindSubject(String interfaceClass,String implementClass) { + if(StringUtils.isNotEmpty(interfaceClass) && StringUtils.isNotEmpty(implementClass)) + { + try { + this.bindDomains.add(new BindDomain(Class.forName(interfaceClass),Class.forName(implementClass))); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return this; + } + return this; + } + return this; + } + + /** + * @Title: addBindSubject + * @Description: 构建服务绑定对象快捷方法 + * @param @param interfaceClass + * @param @param implementClass + * @param @return + * @param @throws ClassNotFoundException 参数 + * @return boolean 返回类型 + * @throws + */ + public BindDomains addBindSubject(Class interfaceClass,Class implementClass){ + if(Objects.nonNull(interfaceClass) && Objects.nonNull(implementClass)) + { + bindDomains.add(new BindDomain(interfaceClass,implementClass)); + return this; + } + return this; + } + + /** + * @param interfaceClass + * @param implementClass + * @return + * @exception + */ + public BindDomains addBindSubjects(Class interfaceClass,List implementClass){ + if(Objects.nonNull(interfaceClass) && Objects.nonNull(implementClass)){ + BindDomain bindModel = new BindDomain(interfaceClass,implementClass); + bindDomains.add(bindModel); + return this; + } + return this; + } + + /** + * @Title: addBindSubject + * @Description: 构建服务绑定对象快捷方法 + * @param @param domain + * @param @return 参数 + * @return boolean 返回类型 + * @throws + */ + public BindDomains addBindSubject(BindDomain domain) + { + if(domain != null) + { + this.bindDomains.add(domain); + return this; + } + return this; + } + + /** + * addBindSubject + *

add the bindSubject info subject

+ * @param domain + * @return + * @exception + */ + public BindDomains addBindSubject(List bindDomainList) + { + if(bindDomainList != null && !bindDomainList.isEmpty()) { + bindDomainList.forEach(param->{ + addBindSubject(param); + }); + } + return this; + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/error/GuiceBindException.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/error/GuiceBindException.java new file mode 100644 index 0000000..b7d31e0 --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/error/GuiceBindException.java @@ -0,0 +1,53 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.error; + +/** + * @Title GuiceBindException.java + * @Package com.hyts.bind.error + * @Description Guice框架绑定操作出现错误的异常类型 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class GuiceBindException extends RuntimeException { + + /** + * 创建一个新的实例-构造器 GuiceBindException. + */ + public GuiceBindException() { + super(); + // TODO Auto-generated constructor stub + } + + /** + * 创建一个新的实例-构造器 GuiceBindException. + * @param arg0 + */ + public GuiceBindException(String arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * 创建一个新的实例-构造器 GuiceBindException. + * @param arg0 + */ + public GuiceBindException(Throwable arg0) { + super(arg0); + // TODO Auto-generated constructor stub + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/facade/BindContext.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/facade/BindContext.java new file mode 100644 index 0000000..e2373c7 --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/facade/BindContext.java @@ -0,0 +1,123 @@ +/* + * Copyright [2018] [Alex/libo(liboware@gmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.facade; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.google.inject.Binding; +import com.google.inject.Key; +import com.hyts.bind.base.BaseInjector; +import com.hyts.bind.domain.BindDomains; +import com.hyts.bind.injector.DefaultClassInjector; + +/** + * @author LiBo/Alex + * @see com.hyts.bind.base.BaseInjector + * @see com.hyts.bind.injector.DefaultClassInjector + * @since V1.0 + * @version V1.0 + */ +public final class BindContext { + + + /** + * @fieldName injector + * @fieldType BaseInjector + */ + private static volatile BaseInjector injector; + + /** + * @fieldName bindDomains + * @fieldType BindDomains + */ + private static volatile BindDomains bindDomains; + + /** + *

是否初始化

+ * @fieldName init + * @fieldType Boolean + */ + private static AtomicBoolean init = new AtomicBoolean(false); + + + /** + * init + *

初始化绑定关系对象

+ * @param bindDomains + * @return + * @exception + */ + public static void init() { + if(Objects.isNull(bindDomains)) { + throw new NullPointerException("传入的对象不可以为空,请检查BindDomains对象状态"); + } + if(!init.get()) { + injector = DefaultClassInjector.getInstance().initBinding(bindDomains); + while(init.compareAndSet(false, true)) {} + } + } + + + /** + * getBean + *

获取绑定对象

+ * @param clazz + * @return + * @exception + */ + public static T getBean(Class clazz){ + init(); + return injector.getInjector().getInstance(clazz); + } + + + /** + * getBindings + *

获取绑定关系集合

+ * @return + * @exception + */ + public static Map, Binding> getBindings() { + init(); + return injector.getInjector().getBindings(); + } + + + /** + * getBinding + *

根据绑定key获取绑定关系对象

+ * @param key + * @return + * @exception + */ + public static Binding getBinding(Key key) { + init(); + return injector.getInjector().getBinding(key); + } + + /** + * createBindDomains + *

创建绑定关系域对象集合

+ * @return + * @exception + */ + public static BindDomains createBindDomains() { + bindDomains = new BindDomains(); + return bindDomains; + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/handler/DefaultBindHandler.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/handler/DefaultBindHandler.java new file mode 100644 index 0000000..d4c4a2a --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/handler/DefaultBindHandler.java @@ -0,0 +1,89 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.handler; + +import java.util.Objects; + +import com.google.inject.Binder; +import com.google.inject.Scopes; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Names; +import com.hyts.bind.base.BaseGuiceHandler; +import com.hyts.bind.domain.BindDomain; +import com.hyts.bind.error.GuiceBindException; +import com.hyts.bind.test.TestBind; + +/** + * @Title DefaultBindHandler.java + * @Package com.hyts.bind.handler + * @Description 默认绑定句柄操作处理控制器依赖注入类组件 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class DefaultBindHandler extends BaseGuiceHandler{ + + /** + * @Fields field:field:{todo}绑定操作服务 + */ + private Binder bind; + + /* (非 Javadoc) + *

Title: bindClass

+ *

Description:

+ * @param domain + * @see com.hyts.bind.base.BaseGuiceHandler#bindClass(java.lang.Object) + */ + @SuppressWarnings("unchecked") + @Override + public void bindClass(BindDomain domain) { + if(domain == null) + throw new GuiceBindException("绑定的对象参数domain为空!"); + if(Objects.nonNull(domain.getInterfaceImplClass())) { + bind.bind(domain.getInterfaceClass()).to(domain.getInterfaceImplClass()).in(domain.isSingleton()?Scopes.SINGLETON:Scopes.NO_SCOPE); + }else if(Objects.nonNull(domain.getMultiImplementClass()) && domain.getMultiImplementClass().size()>0){ + domain.getMultiImplementClass().forEach(param->{ + bind.bind(domain.getInterfaceClass()). + annotatedWith(Names.named(param.getSimpleName().toLowerCase())).to(param).in(domain.isSingleton()?Scopes.SINGLETON:Scopes.NO_SCOPE); + }); + // bind.bind(TestBind.class); + /*Multibinder multiBind = Multibinder.newSetBinder(bind, domain.getInterfaceClass()); + domain.getMultiImplementClass().forEach(paramClass->{ + multiBind.addBinding().to(paramClass); + });*/ + } + + } + + /* (非 Javadoc) + *

Title: bindProvider

+ *

Description:

+ * @param domain + * @see com.hyts.bind.base.BaseGuiceHandler#bindProvider(java.lang.Object) + */ + @Override + public void bindProvider(BindDomain domain) { + + } + + /** + * 创建一个新的实例-构造器 DefaultBindHandler. + * @param bind + */ + public DefaultBindHandler(Binder bind) { + this.bind = bind; + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/injector/DefaultClassInjector.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/injector/DefaultClassInjector.java new file mode 100644 index 0000000..4ba306a --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/injector/DefaultClassInjector.java @@ -0,0 +1,117 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.injector; + +import java.util.Set; + +import com.google.inject.Key; +import com.hyts.bind.base.BaseInjector; +import com.hyts.bind.binder.BinderService; +import com.hyts.bind.domain.BindDomain; +import com.hyts.bind.domain.BindDomains; + +/** + * @Title DefaultBootStrapInjector.java + * @Package com.hyts.bind.injector + * @Description 默认操作服务启动依赖注入操作控制器 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public final class DefaultClassInjector extends BaseInjector{ + + + private static DefaultClassInjector singleSubject = new DefaultClassInjector(); + + + public static DefaultClassInjector getInstance(){ + return singleSubject; + } + + /** + * 创建一个新的实例-构造器 DefaultClassInjector. + * @param domains + */ + + public DefaultClassInjector() { + super(); + } + + /** + * @Title: build + * @Description: 开始启动服务,依赖注入服务 + * @param 参数 + * @return void 返回类型 + * @throws + */ + @Deprecated + private BaseInjector build() { + BaseInjector.init(); + return this; + } + + /** + * initBinding + * initBind增添绑定对象 + *

初始化对象绑定对象操作

+ * @param domains + * @return + * @exception + */ + public BaseInjector initBinding(BindDomains domains){ + defaultBindDomains = domains; + BaseInjector.init(); + return this; + } + + /** + * initBind增添绑定对象 + *

初始化对象绑定对象操作

+ * @return + * @exception + */ + @Deprecated + public DefaultClassInjector initBind(){ + throw new UnsupportedOperationException("过期方法不支持,请调用com.hyts.bind.injector.DefaultClassInjector.initBind(BindDomains)"); +/* defaultBindDomains = new BindDomains(); + return this;*/ + } + + /** + * addBind增添绑定对象 + *

添加绑定对象操作

+ * @param domain 绑定域 + * @return + * @exception + */ + public DefaultClassInjector addBind(BindDomain domain){ + defaultBindDomains.addBindSubject(domain); + return this; + } + + /** + * addBind增添绑定对象 + *

添加绑定对象操作

+ * @param interfaceClass 接口类 + * @param implementClass 接口实现类 + * @return + * @exception + */ + public DefaultClassInjector addBind(Class interfaceClass,Class implementClass){ + defaultBindDomains.addBindSubject(interfaceClass, implementClass); + return this; + } + +} diff --git a/coffice-toolbox-binder/src/main/java/com/hyts/bind/scanner/ScannerAdapter.java b/coffice-toolbox-binder/src/main/java/com/hyts/bind/scanner/ScannerAdapter.java new file mode 100644 index 0000000..bf17119 --- /dev/null +++ b/coffice-toolbox-binder/src/main/java/com/hyts/bind/scanner/ScannerAdapter.java @@ -0,0 +1,76 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.scanner; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * @Title ScannerAdapter.java + * @Package com.hyts.bind.scanner + * @Description 依赖注入框架扫描适配器操作服务
+ * 兼顾起注解以及依赖注入服务的双
+ * 向整合,达到桥接的模式过程
+ * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public final class ScannerAdapter { + + /** + * @Title: scanField + * @Description: 获取指定类中的所有字段相关指定注解类 + * @param @param clazz + * @param @return 参数 + * @return List 返回类型 + * @throws + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Map scanField(Class clazz,Class annotation) + { + Field [] fields = clazz.getDeclaredFields(); + Map annotationMap = new HashMap(); + for(Field field:fields) + { + Annotation fieldAnnotation = field.getAnnotation(annotation); + annotationMap.put(field.getName(),fieldAnnotation); + } + return annotationMap; + } + + /** + * @Title: scanMethod + * @Description: 获取指定类中的所有方法相关指定注解类 + * @param @param clazz + * @param @param annotation + * @param @return 参数 + * @return Map 返回类型 + * @throws + */ + public Map scanMethod(Class clazz,Class annotation) + { + Method [] methods = clazz.getDeclaredMethods(); + Map annotationMap = new HashMap(); + for(Method method:methods) + { + Annotation fieldAnnotation = method.getAnnotation(annotation); + annotationMap.put(method.getName(),fieldAnnotation); + } + return annotationMap; + } +} diff --git a/coffice-toolbox-binder/src/main/resources/TODO b/coffice-toolbox-binder/src/main/resources/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestBind.java b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestBind.java new file mode 100644 index 0000000..46cb136 --- /dev/null +++ b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestBind.java @@ -0,0 +1,77 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import com.google.inject.Inject; +import com.google.inject.Key; +import com.google.inject.name.Named; +import com.hyts.bind.base.BaseInjector; +import com.hyts.bind.binder.BinderService; +import com.hyts.bind.domain.BindDomain; +import com.hyts.bind.domain.BindDomains; +import com.hyts.bind.facade.BindContext; +import com.hyts.bind.injector.DefaultClassInjector; + +import junit.framework.TestCase; + +/** + * @Title TestBind.java + * @Package com.hyts.bind.test + * @Description 测试绑定关系框架依赖注入方式 + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class TestBind { + + @Inject + @Named("testserviceimpl") + TestService service1; + + @Inject + @Named("testserviceimpl2") + TestService service2; + + + @SuppressWarnings("rawtypes") + @Test + public void testMethod() { + + //建立绑定关系依赖注入关系 + BindDomains domains = BindContext.createBindDomains(); + domains.addBindSubjects(TestService.class, + new ArrayList(){ + private static final long serialVersionUID = 1L; + { + add(TestServiceImpl.class); + add(TestServiceImpl2.class); + }}); + //call the object method + TestBind bind = BindContext.getBean(TestBind.class); + + System.out.println(BindContext.getBinding(Key.get(TestServiceImpl.class)).getSource()); + + bind.service1.test(); + bind.service2.test(); + } +} diff --git a/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestService.java b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestService.java new file mode 100644 index 0000000..f1d28c0 --- /dev/null +++ b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestService.java @@ -0,0 +1,32 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.test; + +import com.hyts.bind.annotation.BindInterface; +import com.hyts.bind.binder.BinderService; + +/** + * @Title TestService.java + * @Package com.hyts.bind.test + * @Description TODO(用一句话描述该文件做什么) + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public interface TestService extends BinderService{ + + public void test(); + +} diff --git a/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceController.java b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceController.java new file mode 100644 index 0000000..4e737ae --- /dev/null +++ b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceController.java @@ -0,0 +1,36 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.test; + +import com.google.inject.Inject; + +/** + * @Title TestServiceExternal.java + * @Package com.hyts.bind.test + * @Description TODO(用一句话描述该文件做什么) + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ +public class TestServiceController { + + @Inject + TestService service; + + public void test() + { + service.test(); + } +} diff --git a/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl.java b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl.java new file mode 100644 index 0000000..9af2c88 --- /dev/null +++ b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl.java @@ -0,0 +1,40 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.test; + +import com.hyts.bind.annotation.BindInterface; + +/** + * @Title TestServiceImpl.java + * @Package com.hyts.bind.test + * @Description TODO(用一句话描述该文件做什么) + * @author LiBo/Alex + * @date 2017年10月25日 + * @version V1.0 + */ + +public class TestServiceImpl implements TestService { + + /* (非 Javadoc) + *

Title: test

+ *

Description:

+ * @see com.hyts.bind.test.TestService#test() + */ + @Override + public void test() { + System.out.println("libo的测试方法-test()"); + } + +} diff --git a/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl2.java b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl2.java new file mode 100644 index 0000000..ae422bd --- /dev/null +++ b/coffice-toolbox-binder/src/test/java/com/hyts/bind/test/TestServiceImpl2.java @@ -0,0 +1,37 @@ +/* + * Copyright [2017] [Alex/LiBo(libo2dev.aliyun.com/alex.link@foxmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.bind.test; + +/** + * @Title TestServiceImpl2.java + * @Package com.hyts.bind.test + * @Description TODO(用一句话描述该文件做什么) + * @author LiBo/Alex + * @date 2018年4月16日 + * @version V1.0 + */ +public class TestServiceImpl2 implements TestService { + + /* (非 Javadoc) + *

Title: test

+ *

Description:

+ * @see com.hyts.bind.test.TestService#test() + */ + @Override + public void test() { + System.out.println("qweqw"); + } + +} diff --git a/coffice-toolbox-binder/src/test/resources/TODO b/coffice-toolbox-binder/src/test/resources/TODO new file mode 100644 index 0000000..e69de29 diff --git a/coffice-toolbox-codegen/pom.xml b/coffice-toolbox-codegen/pom.xml new file mode 100644 index 0000000..1c971ef --- /dev/null +++ b/coffice-toolbox-codegen/pom.xml @@ -0,0 +1,107 @@ + + 4.0.0 + + com.hyts + coffice-toolbox + 1.0.0 + + coffice-toolbox-codegen + + UTF-8 + UTF-8 + + UTF-8 + 3.6.0 + + 1.8 + 4.11 + + + + + commons-logging + commons-logging + 1.1.1 + + + + log4j + log4j + 1.2.17 + + + + org.mybatis + mybatis + 3.4.1 + + + + mysql + mysql-connector-java + 5.1.8 + + + + org.mybatis.generator + mybatis-generator-core + 1.3.2 + + + + org.apache.velocity + velocity + 1.7 + + + + commons-collections + commons-collections + 3.2.1 + + + + commons-lang + commons-lang + 2.4 + + + + oro + oro + 2.0.8 + + + com.hyts + coffice-toolbox-template + 1.0.0 + + + + com.jfinal + jfinal + 2.2 + + + jalopy + jalopy + 1.5rc3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + ${jdk.version} + ${jdk.version} + ${project.build.sourceEncoding} + + + + + \ No newline at end of file diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AbstractFileWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AbstractFileWriter.java new file mode 100644 index 0000000..b49c01b --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AbstractFileWriter.java @@ -0,0 +1,46 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +/** + * @title AbstractFileWriter.java + * @package com.hyts.codegen.generator + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public interface AbstractFileWriter { + + /** + * writerInternal-内部写文件-写在项目路径上 + *

内部写文件-写在项目路径上,可以进行访问或者其他用途

+ * @param classpath classpath路径直接生成到项目 + * @param object 传入的泛型对象-屏蔽和抽象传值的可能 + * @return + */ + String writerInternal(String classpath,T object); + + /** + * writerExternal-外部写文件-写在文件系统可以写到系统所在任何位置 + *

外部写文件-写在文件系统可以写到系统所在任何位置

+ * @param classpath outputFile路径直接生成到文件系统 + * @param object 传入的泛型对象-屏蔽和抽象传值的可能 + * @return + */ + String writerExternal(String outputFile,T object); +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AnnotationModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AnnotationModel.java new file mode 100644 index 0000000..ad09f72 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/AnnotationModel.java @@ -0,0 +1,96 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import java.util.Map; + +/** + * @title AnnotationModel.java + * @package com.hyts.codegen.base + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class AnnotationModel { + + + /** + *

注解JAVADOC

+ * @fieldName annotationMap + * @fieldType Map + */ + private Map annotationMap; + + /** + *

预留空格数目-手动指定

+ * @fieldName headSpace + * @fieldType String + */ + private String headSpace; + + /** + * @constructor:AnnotationModel + * @param annotationMap + * @param headSpace + */ + + + public AnnotationModel(Map annotationMap, String headSpace) { + super(); + this.annotationMap = annotationMap; + this.headSpace = headSpace; + } + + /** + * @name annotationMap's getter method + * @param none + * @return annotationMap + */ + public Map getAnnotationMap() { + return annotationMap; + } + + /** + * @name annotationMap's setter method + * @param annotationMap + * @return void + */ + public void setAnnotationMap(Map annotationMap) { + this.annotationMap = annotationMap; + } + + /** + * @name headSpace's getter method + * @param none + * @return headSpace + */ + public String getHeadSpace() { + return headSpace; + } + + /** + * @name headSpace's setter method + * @param headSpace + * @return void + */ + public void setHeadSpace(String headSpace) { + this.headSpace = headSpace; + } + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/BuildModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/BuildModel.java new file mode 100644 index 0000000..fbffe42 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/BuildModel.java @@ -0,0 +1,67 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import java.util.Map; + +/** + * @title BuildModel.java + * @package com.hyts.codegen.base + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class BuildModel { + + /** + *

{字段的描述}

+ * @fieldName basePackageName + * @fieldType String + */ + private String basePackageName; + + /** + *

{字段的描述}

+ * @fieldName modelPackageName + * @fieldType String + */ + private String modelPackageName; + + /** + *

{字段的描述}

+ * @fieldName importClasses + * @fieldType String[] + */ + private String[] importClasses; + + /** + *

{字段的描述}

+ * @fieldName docModel + * @fieldType JavaDocModel + */ + private JavaDocModel docModel; + + /** + *

{字段的描述}

+ * @fieldName typeModel + * @fieldType JavaTypeModel + */ + private JavaTypeModel typeModel; + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/Generator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/Generator.java new file mode 100644 index 0000000..484e151 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/Generator.java @@ -0,0 +1,18 @@ +package com.hyts.codegen.base; + +/** + * project-name:coffice-wizard + * package-name:com.hyts.codegen.base + * author:Libo/Alex + * create-date:2018-11-04 14:12 + * copyright:libo-hyts-github + * email:libo2dev@aliyun.com + * description:此类主要用于: 定义生成器的接口服务 + */ +public interface Generator { + + R generateInternal(P... params); + + R generateExternal(P... params); + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaDocModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaDocModel.java new file mode 100644 index 0000000..d299222 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaDocModel.java @@ -0,0 +1,96 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import java.util.Map; + +/** + * @title AnnotationModel.java + * @package com.hyts.codegen.base + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JavaDocModel { + + + /** + *

注解JAVADOC

+ * @fieldName annotationMap + * @fieldType Map + */ + private Map annotationMap; + + /** + *

预留空格数目-手动指定

+ * @fieldName headSpace + * @fieldType String + */ + private String headSpace; + + /** + * @constructor:AnnotationModel + * @param annotationMap + * @param headSpace + */ + + + public JavaDocModel(Map annotationMap, String headSpace) { + super(); + this.annotationMap = annotationMap; + this.headSpace = headSpace; + } + + /** + * @name annotationMap's getter method + * @param none + * @return annotationMap + */ + public Map getAnnotationMap() { + return annotationMap; + } + + /** + * @name annotationMap's setter method + * @param annotationMap + * @return void + */ + public void setAnnotationMap(Map annotationMap) { + this.annotationMap = annotationMap; + } + + /** + * @name headSpace's getter method + * @param none + * @return headSpace + */ + public String getHeadSpace() { + return headSpace; + } + + /** + * @name headSpace's setter method + * @param headSpace + * @return void + */ + public void setHeadSpace(String headSpace) { + this.headSpace = headSpace; + } + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaFieldModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaFieldModel.java new file mode 100644 index 0000000..7553d98 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaFieldModel.java @@ -0,0 +1,154 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +/** + * @title JavaFieldModel.java + * @package com.hyts.codegen.base + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JavaFieldModel { + + /** + *

访问类型

+ * @fieldName accessType + * @fieldType String + */ + private String accessType; + + /** + *

返回类型

+ * @fieldName returnType + * @fieldType String + */ + private String returnType; + + /** + *

字段名称

+ * @fieldName fieldName + * @fieldType String + */ + private String fieldName; + + /** + *

开头空格间隔

+ * @fieldName headSpace + * @fieldType String + */ + private String headSpace; + + /** + *

方法的注解

+ * @fieldName annotations + * @fieldType String[] + */ + private String[] annotations; + + /** + * @name accessType's getter method + * @param none + * @return accessType + */ + public String getAccessType() { + return accessType; + } + + /** + * @name accessType's setter method + * @param accessType + * @return void + */ + public void setAccessType(String accessType) { + this.accessType = accessType; + } + + /** + * @name returnType's getter method + * @param none + * @return returnType + */ + public String getReturnType() { + return returnType; + } + + /** + * @name returnType's setter method + * @param returnType + * @return void + */ + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + /** + * @name fieldName's getter method + * @param none + * @return fieldName + */ + public String getFieldName() { + return fieldName; + } + + /** + * @name fieldName's setter method + * @param fieldName + * @return void + */ + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + /** + * @name headSpace's getter method + * @param none + * @return headSpace + */ + public String getHeadSpace() { + return headSpace; + } + + /** + * @name headSpace's setter method + * @param headSpace + * @return void + */ + public void setHeadSpace(String headSpace) { + this.headSpace = headSpace; + } + + /** + * @name annotations's getter method + * @param none + * @return annotations + */ + public String[] getAnnotations() { + return annotations; + } + + /** + * @name annotations's setter method + * @param annotations + * @return void + */ + public void setAnnotations(String[] annotations) { + this.annotations = annotations; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaMethodModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaMethodModel.java new file mode 100644 index 0000000..0450cda --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaMethodModel.java @@ -0,0 +1,206 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import java.util.Map; + +/** + * @title JavaMethodModel.java + * @package com.hyts.codegen.base + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JavaMethodModel { + + /** + *

访问类型

+ * @fieldName accessType + * @fieldType String + */ + private String accessType; + + /** + *

返回类型

+ * @fieldName returnType + * @fieldType String + */ + private String returnType; + + /** + *

方法名称

+ * @fieldName methodName + * @fieldType String + */ + private String methodName; + + /** + *

开头空格间隔

+ * @fieldName headSpace + * @fieldType String + */ + private String headSpace; + + /** + *

方法的注解

+ * @fieldName annotations + * @fieldType String[] + */ + private String[] annotations; + + /** + *

方法体

+ * @fieldName functionBody + * @fieldType String + */ + private String functionBody; + + /** + *

参数列表

+ * @fieldName paramList + * @fieldType Map + */ + private Map paramList; + + /** + * @name accessType's getter method + * @param none + * @return accessType + */ + public String getAccessType() { + return accessType; + } + + /** + * @name accessType's setter method + * @param accessType + * @return void + */ + public void setAccessType(String accessType) { + this.accessType = accessType; + } + + /** + * @name returnType's getter method + * @param none + * @return returnType + */ + public String getReturnType() { + return returnType; + } + + /** + * @name returnType's setter method + * @param returnType + * @return void + */ + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + /** + * @name methodName's getter method + * @param none + * @return methodName + */ + public String getMethodName() { + return methodName; + } + + /** + * @name methodName's setter method + * @param methodName + * @return void + */ + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + /** + * @name headSpace's getter method + * @param none + * @return headSpace + */ + public String getHeadSpace() { + return headSpace; + } + + /** + * @name headSpace's setter method + * @param headSpace + * @return void + */ + public void setHeadSpace(String headSpace) { + this.headSpace = headSpace; + } + + /** + * @name annotations's getter method + * @param none + * @return annotations + */ + public String[] getAnnotations() { + return annotations; + } + + /** + * @name annotations's setter method + * @param annotations + * @return void + */ + public void setAnnotations(String[] annotations) { + this.annotations = annotations; + } + + /** + * @name functionBody's getter method + * @param none + * @return functionBody + */ + public String getFunctionBody() { + return functionBody; + } + + /** + * @name functionBody's setter method + * @param functionBody + * @return void + */ + public void setFunctionBody(String functionBody) { + this.functionBody = functionBody; + } + + /** + * @name paramList's getter method + * @param none + * @return paramList + */ + public Map getParamList() { + return paramList; + } + + /** + * @name paramList's setter method + * @param paramList + * @return void + */ + public void setParamList(Map paramList) { + this.paramList = paramList; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaModel.java new file mode 100644 index 0000000..ee89aad --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaModel.java @@ -0,0 +1,209 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import java.util.List; +import java.util.Map; + +import com.hyts.codegen.jfinal.config.JfinalParamConfig; + +/** + * @title BuildModel.java + * @package com.hyts.codegen.base + * @description 代表一个java文件生成的模型 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JavaModel { + + /** + *

基础包字段

+ * @fieldName basePackageName + * @fieldType String + */ + private String basePackageName; + + /** + *

模型包字段

+ * @fieldName modelPackageName + * @fieldType String + */ + private String modelPackageName; + + /** + *

引入java类的代码

+ * @fieldName importClasses + * @fieldType String[] + */ + private String[] importClasses; + + /** + *

javaDoc的模型类

+ * @fieldName docModel + * @fieldType JavaDocModel + */ + private JavaDocModel docModel; + + /** + *

type类型模型

+ * @fieldName typeModel + * @fieldType JavaTypeModel + */ + private JavaTypeModel typeModel; + + /** + *

{字段的描述}

+ * @fieldName fieldModel + * @fieldType List + */ + private List fieldModels; + + /** + *

{字段的描述}

+ * @fieldName methodModels + * @fieldType List + */ + private List methodModels; + + /** + * @name basePackageName's getter method + * @param none + * @return basePackageName + */ + public String getBasePackageName() { + return basePackageName; + } + + /** + * @name basePackageName's setter method + * @param basePackageName + * @return void + */ + public void setBasePackageName(String basePackageName) { + this.basePackageName = basePackageName; + } + + /** + * @name modelPackageName's getter method + * @param none + * @return modelPackageName + */ + public String getModelPackageName() { + return modelPackageName; + } + + /** + * @name modelPackageName's setter method + * @param modelPackageName + * @return void + */ + public void setModelPackageName(String modelPackageName) { + this.modelPackageName = modelPackageName; + } + + /** + * @name importClasses's getter method + * @param none + * @return importClasses + */ + public String[] getImportClasses() { + return importClasses; + } + + /** + * @name importClasses's setter method + * @param importClasses + * @return void + */ + public void setImportClasses(String[] importClasses) { + this.importClasses = importClasses; + } + + /** + * @name docModel's getter method + * @param none + * @return docModel + */ + public JavaDocModel getDocModel() { + return docModel; + } + + /** + * @name docModel's setter method + * @param docModel + * @return void + */ + public void setDocModel(JavaDocModel docModel) { + this.docModel = docModel; + } + + /** + * @name typeModel's getter method + * @param none + * @return typeModel + */ + public JavaTypeModel getTypeModel() { + return typeModel; + } + + /** + * @name typeModel's setter method + * @param typeModel + * @return void + */ + public void setTypeModel(JavaTypeModel typeModel) { + this.typeModel = typeModel; + } + + /** + * @name fieldModels's getter method + * @param none + * @return fieldModels + */ + public List getFieldModels() { + return fieldModels; + } + + /** + * @name fieldModels's setter method + * @param fieldModels + * @return void + */ + public void setFieldModels(List fieldModels) { + this.fieldModels = fieldModels; + } + + /** + * @name methodModels's getter method + * @param none + * @return methodModels + */ + public List getMethodModels() { + return methodModels; + } + + /** + * @name methodModels's setter method + * @param methodModels + * @return void + */ + public void setMethodModels(List methodModels) { + this.methodModels = methodModels; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaTypeModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaTypeModel.java new file mode 100644 index 0000000..c5d3697 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/base/JavaTypeModel.java @@ -0,0 +1,131 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.base; + +import com.hyts.template.config.JavaTemplateConfig.JavaType; + +/** + * @title JavaTypeModel.java + * @package com.hyts.codegen.base + * @description javaType类模型 + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JavaTypeModel { + + /** + *

java文件类型:枚举、接口、类

+ * @fieldName javaType + * @fieldType JavaType + */ + private JavaType javaType; + + /** + *

访问类型:public/private/protected

+ * @fieldName accessType + * @fieldType String + */ + private String accessType; + + /** + *

类名

+ * @fieldName className + * @fieldType String + */ + private String className; + + /** + *

注解集合所包含的注解

+ * @fieldName annotations + * @fieldType String[] + */ + private String[] annotations; + + /** + * @name javaType's getter method + * @param none + * @return javaType + */ + public JavaType getJavaType() { + return javaType; + } + + /** + * @name javaType's setter method + * @param javaType + * @return void + */ + public void setJavaType(JavaType javaType) { + this.javaType = javaType; + } + + /** + * @name accessType's getter method + * @param none + * @return accessType + */ + public String getAccessType() { + return accessType; + } + + /** + * @name accessType's setter method + * @param accessType + * @return void + */ + public void setAccessType(String accessType) { + this.accessType = accessType; + } + + /** + * @name className's getter method + * @param none + * @return className + */ + public String getClassName() { + return className; + } + + /** + * @name className's setter method + * @param className + * @return void + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * @name annotations's getter method + * @param none + * @return annotations + */ + public String[] getAnnotations() { + return annotations; + } + + /** + * @name annotations's setter method + * @param annotations + * @return void + */ + public void setAnnotations(String[] annotations) { + this.annotations = annotations; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/JfinalGenerator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/JfinalGenerator.java new file mode 100644 index 0000000..5aef690 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/JfinalGenerator.java @@ -0,0 +1,175 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal; + +import com.hyts.codegen.jfinal.base.BaseJfinalCreator; +import com.hyts.codegen.jfinal.creator.DefaultJfinalCodeCreator; +import com.hyts.codegen.jfinal.model.SimpleBuildModel; +import com.hyts.guava.String.Strings; +import com.hyts.guava.object.Objects; +import com.hyts.template.common.AbstractFileWriter; +import com.hyts.template.strformat.JavaCodeExecutor; + +/** + * @title JfinalGenerator.java + * @package com.hyts.codegen.jfinal + * @description TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JfinalGenerator { + + /** + *

{字段的描述}

+ * @fieldName creator + * @fieldType BaseJfinalCreator + */ + BaseJfinalCreator creator; + + /** + *

{字段的描述}

+ * @fieldName fileWriter + * @fieldType AbstractFileWriter + */ + AbstractFileWriter fileWriter; + + /** + * @constructor:JfinalGenerator + * @param creator + */ + public JfinalGenerator(BaseJfinalCreator creator) { + super(); + Objects.checkNull(creator); + this.creator = creator; + } + + public JfinalGenerator() { + super(); + this.creator = new DefaultJfinalCodeCreator(); + this.fileWriter = new JavaCodeExecutor(); + } + + /** + * createModelInternal + *

创建模型成功

+ * @param model + * @return + * @exception + */ + public String createModelInternal(SimpleBuildModel model){ + String javaFullPath = model.getBasePackageName().replace(".","/")+"/"+model.getModelPackageName()+"/"+model.getJavaTypeName()+".java"; + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + model.setAnnotations(new String[]{"Entity(tableName=\""+Strings.upperCamelToUnderLineUpperCase(model.getJavaTypeName())+"\")"}); + model.setImportClassName(new String[]{"import com.hyts.jfmvc.scan.annotation.Entity"}); + } + return this.fileWriter.writerInternal(javaFullPath, this.creator.buildModel(model)); + } + + /** + * createModelExternal + *

创建模型成功

+ * @param model + * @return + * @exception + */ + public String createModelExternal(SimpleBuildModel model){ + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + model.setAnnotations(new String[]{"Entity(tableName=\""+model.TABLE_MODEL_PREFIX+Strings.upperCamelToUnderLineUpperCase(model.getJavaTypeName())+"\")"}); + model.setImportClassName(new String[]{"import com.hyts.jfmvc.scan.annotation.Entity"}); + } + return this.fileWriter.writerExternal(model.getExternalFilePath()+model.getBasePackageName().replace(".","/")+"/"+model.getModelPackageName()+"/"+model.getJavaTypeName()+".java", + this.creator.buildModel(model)); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + public String createDaoInternal(SimpleBuildModel model){ + String javaFullPath = model.getBasePackageName().replace(".","/")+"/"+model.getModelPackageName()+"/"+model.getJavaTypeName()+".java"; + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + model.setAnnotations(new String[]{"Repository"}); + } + return this.fileWriter.writerInternal(javaFullPath, this.creator.buildDao(model)); + } + + /** + * + * @param model + * @return + */ + public String createDaoExternal(SimpleBuildModel model){ + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + model.setAnnotations(new String[]{"Repository"}); + model.setImportClassName(new String[]{"import com.hyts.jfmvc.scan.annotation.Repository"}); + } + return this.fileWriter.writerExternal(model.getExternalFilePath() + +model.getBasePackageName().replace(".","/")+"/" + +model.getModelPackageName()+"/"+model.getJavaTypeName()+".java", + this.creator.buildDao(model)); + } + + /** + * @param model + * @return + * @exception + */ + public String createServiceInternal(SimpleBuildModel model){ + String javaFullPath = model.getBasePackageName().replace(".","/")+"/"+model.getModelPackageName()+"/"+model.getJavaTypeName()+".java"; + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + if(model.isInterface()) + model.setAnnotations(new String[]{}); + else { + model.setAnnotations(new String[]{"Service"}); + } + } + return this.fileWriter.writerInternal(javaFullPath, this.creator.buildService(model)); + } + + + /** + * @param model + * @return + * @exception + */ + public String createControllerInternal(SimpleBuildModel model,String modelName){ + String javaFullPath = model.getBasePackageName().replace(".","/")+"/"+model.getModelPackageName()+"/"+model.getJavaTypeName()+".java"; + //如果采用jfinal原生的代码生成方法 + if(!model.usedJfinalPrototype) { + model.setAnnotations(new String[]{String.format("Controller(\"/%s\")",modelName)}); + } + return this.fileWriter.writerInternal(javaFullPath, this.creator.buildController(model)); + } + + /** + * + * @param model + * @return + */ + public String createServiceExternal(SimpleBuildModel model){ + return null; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalCreator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalCreator.java new file mode 100644 index 0000000..6a26895 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalCreator.java @@ -0,0 +1,67 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.base; + +/** + * @title BaseJfinalWriter.java + * @package com.hyts.codegen.jfinal.writer + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public interface BaseJfinalCreator { + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildModel(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildDao(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildService(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildController(T model); + + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalWriter.java new file mode 100644 index 0000000..e2f39ab --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/BaseJfinalWriter.java @@ -0,0 +1,67 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.base; + +/** + * @title BaseJfinalWriter.java + * @package com.hyts.codegen.jfinal.writer + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public interface BaseJfinalWriter { + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildModel(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildDao(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildService(T model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildController(T model); + + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JFinalWriterConfig.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JFinalWriterConfig.java new file mode 100644 index 0000000..ebd1432 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JFinalWriterConfig.java @@ -0,0 +1,41 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.base; + +import java.io.File; + +import com.hyts.guava.String.Strings; + +/** + * @title JFinalWriterConfig.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JFinalWriterConfig { + + /** + *

JFINAL_MAVEN_BASE_PATH:JFINAL-MAVEN基础项目路径

+ * @fieldName JFINAL_MAVEN_BASE_PATH + * @fieldType String + */ + public static final String JFINAL_MAVEN_BASE_PATH = + System.getProperty("user.dir")+File.separator+Strings.join(new String[]{"src","main","java"},File.separator)+File.separator; + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JavaCodeWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JavaCodeWriter.java new file mode 100644 index 0000000..8ee0156 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JavaCodeWriter.java @@ -0,0 +1,120 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.base; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import com.alibaba.fastjson.util.IOUtils; +import com.google.common.base.Charsets; +import com.hyts.codegen.base.AbstractFileWriter; +import com.hyts.codegen.jfinal.config.JavaWriterConfig; +import com.hyts.guava.exception.Exceptions; +import com.hyts.guava.object.Objects; +import com.hyts.logger.factory.LoggerFactory; +import com.hyts.template.common.BaseJavaFileTemplate; +import com.hyts.template.strformat.JavaCodeTemplate; + +/** + * @title FileWriterHandler.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JavaCodeWriter implements AbstractFileWriter{ + + /** + *

日志输出器}

+ * @fieldName logger + * @fieldType Logger + */ + private static Logger logger = LoggerFactory.getLogger(JavaCodeWriter.class); + + + + /* (非 Javadoc) + * @param classpath + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerInternal(String classpath, String object) { + Objects.checkNull(classpath);Objects.checkNull(object); + String url = JavaWriterConfig.JFINAL_MAVEN_BASE_PATH + + classpath.replace("/",File.separator); + Path filePath = Paths.get(url); + logger.info("【coffice-toolbox-codegen】- 生成文件路径文件:"+url); + File parentFile = filePath.getParent().toFile(); + if(!filePath.getParent().toFile().exists()){ + parentFile.mkdirs(); + } + BufferedWriter writer = null; + try{ + Files.deleteIfExists(filePath); + Files.createFile(filePath); + writer = Files.newBufferedWriter(filePath, Charsets.UTF_8, LinkOption.NOFOLLOW_LINKS); + writer.write(object); + } catch (IOException e) { + Exceptions.throwRuntimeException(e); + } finally{ + IOUtils.close(writer); + } + return filePath.toString(); + } + + /* (非 Javadoc) + * @param outputFile + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, String object) { + // TODO Auto-generated method stub + return null; + } + + public static void main(String[] args) { + BaseJavaFileTemplate tempate = new JavaCodeTemplate(); + tempate.genPackageContent("com.hyts.codegen", new String[]{"test"}); + tempate.genImportContent(new String[]{"import java.util.Map;","import java.util.logging.Logger;"}); + Map annotationMap = new HashMap<>(); + annotationMap.put("author","alex/libo"); + annotationMap.put("date","20180509"); + annotationMap.put("description","om.hyts.codegen.generator.AbstractFileWriter#writerEx"); + tempate.genJavaDocContent(annotationMap,""); + tempate.genTypeContent(null, null, "test", null); + tempate.genFieldContent(null, "String", "name", " ", null); + new JavaCodeWriter().writerInternal("com/hyts/codegen/test/test.java",tempate.end().toString()); + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JfinalCodeWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JfinalCodeWriter.java new file mode 100644 index 0000000..4a11ede --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/base/JfinalCodeWriter.java @@ -0,0 +1,105 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.base; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import com.alibaba.fastjson.util.IOUtils; +import com.google.common.base.Charsets; +import com.hyts.codegen.base.AbstractFileWriter; +import com.hyts.codegen.jfinal.config.JFinalWriterConfig; +import com.hyts.guava.exception.Exceptions; +import com.hyts.guava.object.Objects; +import com.hyts.logger.factory.LoggerFactory; +import com.hyts.template.common.BaseJavaFileTemplate; +import com.hyts.template.strformat.JavaCodeTemplate; + +/** + * @title FileWriterHandler.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JfinalCodeWriter implements AbstractFileWriter{ + + /** + *

日志输出器}

+ * @fieldName logger + * @fieldType Logger + */ + private static Logger logger = LoggerFactory.getLogger(JavaCodeWriter.class); + + + + /* (非 Javadoc) + * @param classpath + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerInternal(String classpath, String object) { + Objects.checkNull(classpath);Objects.checkNull(object); + String url = JFinalWriterConfig.JFINAL_MAVEN_BASE_PATH + + classpath.replace("/",File.separator); + Path filePath = Paths.get(url); + logger.info("【coffice-toolbox-codegen】- 生成文件路径文件:"+url); + File parentFile = filePath.getParent().toFile(); + if(!filePath.getParent().toFile().exists()){ + parentFile.mkdirs(); + } + BufferedWriter writer = null; + try{ + Files.deleteIfExists(filePath); + Files.createFile(filePath); + writer = Files.newBufferedWriter(filePath, Charsets.UTF_8, LinkOption.NOFOLLOW_LINKS); + writer.write(object); + } catch (IOException e) { + Exceptions.throwRuntimeException(e); + } finally{ + IOUtils.close(writer); + } + return filePath.toString(); + } + + /* (非 Javadoc) + * @param outputFile + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, String object) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/build/JfinalExcBuilder.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/build/JfinalExcBuilder.java new file mode 100644 index 0000000..06dec56 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/build/JfinalExcBuilder.java @@ -0,0 +1,112 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.build; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.logging.Logger; + +import com.alibaba.fastjson.util.IOUtils; +import com.google.common.base.Charsets; +import com.hyts.codegen.jfinal.base.BaseJfinalCreator; +import com.hyts.codegen.jfinal.creator.DefaultJfinalCodeCreator; +import com.hyts.codegen.jfinal.model.JfinalBuildModel; +import com.hyts.codegen.jfinal.model.SimpleBuildModel; +import com.hyts.guava.exception.Exceptions; +import com.hyts.guava.object.Objects; +import com.hyts.logger.factory.LoggerFactory; +import com.hyts.template.common.AbstractFileWriter; +import com.hyts.template.strformat.JavaCodeConfig; + +/** + * @title JfinalExcBuilder.java + * @package com.hyts.codegen.jfinal.build + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JfinalExcBuilder implements AbstractFileWriter { + + + Logger logger = LoggerFactory.getLogger(JfinalExcBuilder.class); + + BaseJfinalCreator creator = null; + /** + * @constructor:JfinalExcBuilder + */ + public JfinalExcBuilder() { + super(); + creator = new DefaultJfinalCodeCreator(); + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- writerInternal + *

TODO(这里用一句话描述这个方法的作用)

+ * @param classpath + * @param object + * @return + * @see com.hyts.template.common.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + @Override + public String writerInternal(String classpath, SimpleBuildModel object) { + Objects.checkNull(classpath);Objects.checkNull(object); + String url = JavaCodeConfig.MAVEN_BASE_PATH + + classpath.replace("/",File.separator); + Path filePath = Paths.get(url); + logger.info("【coffice-toolbox-codegen】- 生成文件路径文件:"+url); + File parentFile = filePath.getParent().toFile(); + if(!filePath.getParent().toFile().exists()){ + parentFile.mkdirs(); + } + BufferedWriter writer = null; + try{ + Files.deleteIfExists(filePath); + Files.createFile(filePath); + writer = Files.newBufferedWriter(filePath, Charsets.UTF_8, LinkOption.NOFOLLOW_LINKS); + writer.write(creator.buildModel(object)); + } catch (IOException e) { + Exceptions.throwRuntimeException(e); + } finally{ + IOUtils.close(writer); + } + return filePath.toString(); + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- writerExternal + *

TODO(这里用一句话描述这个方法的作用)

+ * @param outputFile + * @param object + * @return + * @see com.hyts.template.common.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, SimpleBuildModel object) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JFinalWriterConfig.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JFinalWriterConfig.java new file mode 100644 index 0000000..c3f11bd --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JFinalWriterConfig.java @@ -0,0 +1,41 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.config; + +import java.io.File; + +import com.hyts.guava.String.Strings; + +/** + * @title JFinalWriterConfig.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JFinalWriterConfig { + + /** + *

JFINAL_MAVEN_BASE_PATH:JFINAL-MAVEN基础项目路径

+ * @fieldName JFINAL_MAVEN_BASE_PATH + * @fieldType String + */ + public static final String JFINAL_MAVEN_BASE_PATH = + /*System.getProperty("user.dir")+File.separator+*/Strings.join(new String[]{"src","main","java"},File.separator)+File.separator; + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JavaWriterConfig.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JavaWriterConfig.java new file mode 100644 index 0000000..2cea7ec --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JavaWriterConfig.java @@ -0,0 +1,41 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.config; + +import java.io.File; + +import com.hyts.guava.String.Strings; + +/** + * @title JFinalWriterConfig.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JavaWriterConfig { + + /** + *

JFINAL_MAVEN_BASE_PATH:JFINAL-MAVEN基础项目路径

+ * @fieldName JFINAL_MAVEN_BASE_PATH + * @fieldType String + */ + public static final String JFINAL_MAVEN_BASE_PATH = + /*System.getProperty("user.dir")+File.separator+*/Strings.join(new String[]{"src","main","java"},File.separator)+File.separator; + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JfinalParamConfig.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JfinalParamConfig.java new file mode 100644 index 0000000..93fdf6a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/config/JfinalParamConfig.java @@ -0,0 +1,37 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.config; + +import java.util.HashMap; +import java.util.Map; + +/** + * @title JfinalParamConfig.java + * @package com.hyts.codegen.jfinal.config + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JfinalParamConfig { + + + public static final String TABLE_MODEL_PREFIX = "TBL_"; + + public boolean usedJfinalPrototype = false; + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodeCreator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodeCreator.java new file mode 100644 index 0000000..b28a4c2 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodeCreator.java @@ -0,0 +1,195 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.creator; + +import java.util.HashMap; +import java.util.Map; + +import com.hyts.codegen.base.JavaFieldModel; +import com.hyts.codegen.jfinal.base.BaseJfinalCreator; +import com.hyts.codegen.jfinal.model.JfinalBuildModel; +import com.hyts.codegen.jfinal.model.SimpleBuildModel; +import com.hyts.guava.String.Strings; +import com.hyts.guava.object.Objects; +import com.hyts.template.common.AbstractFileWriter; +import com.hyts.template.common.BaseJavaFileTemplate; +import com.hyts.template.strformat.JavaCodeTemplate; + +/** + * @title DefaultJfinalCodeCreator.java + * @package com.hyts.codegen.jfinal.creator + * @description TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class DefaultJfinalCodeCreator implements + BaseJfinalCreator { + + /** + *

{字段的描述}

+ * @fieldName codeTemplate + * @fieldType BaseJavaFileTemplate + */ + private BaseJavaFileTemplate codeTemplate; + + /** + * @constructor:DefaultJfinalCodeCreator + */ + public DefaultJfinalCodeCreator( + BaseJavaFileTemplate codeTemplate) { + Objects.checkNull(codeTemplate); + this.codeTemplate = codeTemplate; + } + + public DefaultJfinalCodeCreator() { + super(); + this.codeTemplate = new JavaCodeTemplate(); + } + + /* (非 Javadoc) + * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildModel(java.lang.Object) + * @exception + */ + + @Override + public String buildModel(SimpleBuildModel model) { + JfinalBuildModel jfinalModel = new JfinalBuildModel(model).initModel(); + if(Strings.isNotEmpty(codeTemplate.getJavaCode().toString())) + codeTemplate.flushJavaCode(); + codeTemplate.genPackageContent(jfinalModel.getBasePackageName(),jfinalModel.getModelPackageName()); + codeTemplate.genImportContent(jfinalModel.getImportClasses()); + codeTemplate.genJavaDocContent(jfinalModel.getDocModel().getAnnotationMap(),""); + codeTemplate.genTypeContent(jfinalModel.getTypeModel().getJavaType(), + jfinalModel.getTypeModel().getAccessType(), + jfinalModel.getTypeModel().getClassName(), + jfinalModel.getTypeModel().getAnnotations()); + codeTemplate.genFieldContent(jfinalModel.getFieldModels().get(0).getAccessType(), + jfinalModel.getFieldModels().get(0).getReturnType(), + jfinalModel.getFieldModels().get(0).getFieldName(), + jfinalModel.getFieldModels().get(0).getHeadSpace(), + jfinalModel.getFieldModels().get(0).getAnnotations()); + return codeTemplate.end().toString(); + } + + /* (非 Javadoc) + * 构建JFINAL框架基础结构代码- buildDao + * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildDao(java.lang.Object) + * @exception + */ + + @Override + public String buildDao(SimpleBuildModel model) { + JfinalBuildModel jfinalModel = new JfinalBuildModel(model).initDao(); + if(Strings.isNotEmpty(codeTemplate.getJavaCode().toString())) + codeTemplate.flushJavaCode(); + codeTemplate.genPackageContent(jfinalModel.getBasePackageName(),jfinalModel.getModelPackageName()); + codeTemplate.genImportContent(jfinalModel.getImportClasses()); + codeTemplate.genJavaDocContent(jfinalModel.getDocModel().getAnnotationMap(),""); + codeTemplate.genTypeContent(jfinalModel.getTypeModel().getJavaType(), + jfinalModel.getTypeModel().getAccessType(), + jfinalModel.getTypeModel().getClassName(), + jfinalModel.getTypeModel().getAnnotations()); + for(int i = 0 ; i< jfinalModel.getMethodModels().size() ; i++){ + codeTemplate.genMethodContent(jfinalModel.getMethodModels().get(i).getAccessType(), + jfinalModel.getMethodModels().get(i).getReturnType(), + jfinalModel.getMethodModels().get(i).getMethodName(), + jfinalModel.getMethodModels().get(i).getParamList(), + jfinalModel.getMethodModels().get(i).getFunctionBody(), + jfinalModel.getMethodModels().get(i).getHeadSpace(), + jfinalModel.getMethodModels().get(i).getAnnotations()); + } + return codeTemplate.end().toString(); + } + + /* + * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildService(java.lang.Object) + * @exception + */ + + @Override + public String buildService(SimpleBuildModel model) { + JfinalBuildModel jfinalModel = new JfinalBuildModel(model).initService(model.isInterface()); + if(Strings.isNotEmpty(codeTemplate.getJavaCode().toString())) + codeTemplate.flushJavaCode(); + codeTemplate.genPackageContent(jfinalModel.getBasePackageName(),jfinalModel.getModelPackageName()); + codeTemplate.genImportContent(jfinalModel.getImportClasses()); + codeTemplate.genJavaDocContent(jfinalModel.getDocModel().getAnnotationMap(),""); + codeTemplate.genTypeContent(jfinalModel.getTypeModel().getJavaType(), + jfinalModel.getTypeModel().getAccessType(), + jfinalModel.getTypeModel().getClassName(), + jfinalModel.getTypeModel().getAnnotations()); + if(jfinalModel.getFieldModels() != null && jfinalModel.getFieldModels().size() > 0) { + for (int j = 0; j < jfinalModel.getFieldModels().size(); j++) { + JavaFieldModel field = jfinalModel.getFieldModels().get(j); + codeTemplate.genFieldContent(field.getAccessType(), field.getReturnType(), field.getFieldName(), field.getHeadSpace(), field.getAnnotations()); + } + } + for(int i = 0 ; i< jfinalModel.getMethodModels().size() ; i++){ + codeTemplate.genMethodContent(jfinalModel.getMethodModels().get(i).getAccessType(), + jfinalModel.getMethodModels().get(i).getReturnType(), + jfinalModel.getMethodModels().get(i).getMethodName(), + jfinalModel.getMethodModels().get(i).getParamList(), + jfinalModel.getMethodModels().get(i).getFunctionBody(), + jfinalModel.getMethodModels().get(i).getHeadSpace(),model.isInterface(), + jfinalModel.getMethodModels().get(i).getAnnotations()); + } + return codeTemplate.end().toString(); + } + + /* (非 Javadoc) + * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildController(java.lang.Object) + * @exception + */ + + @Override + public String buildController(SimpleBuildModel model) { + JfinalBuildModel jfinalModel = new JfinalBuildModel(model).initController(); + if(Strings.isNotEmpty(codeTemplate.getJavaCode().toString())) + codeTemplate.flushJavaCode(); + codeTemplate.genPackageContent(jfinalModel.getBasePackageName(),jfinalModel.getModelPackageName()); + codeTemplate.genImportContent(jfinalModel.getImportClasses()); + codeTemplate.genJavaDocContent(jfinalModel.getDocModel().getAnnotationMap(),""); + codeTemplate.genTypeContent(jfinalModel.getTypeModel().getJavaType(), + jfinalModel.getTypeModel().getAccessType(), + jfinalModel.getTypeModel().getClassName(), + jfinalModel.getTypeModel().getAnnotations()); + codeTemplate.genFieldContent(jfinalModel.getFieldModels().get(0).getAccessType(), + jfinalModel.getFieldModels().get(0).getReturnType(), + jfinalModel.getFieldModels().get(0).getFieldName(), + jfinalModel.getFieldModels().get(0).getHeadSpace(), + jfinalModel.getFieldModels().get(0).getAnnotations()); + for(int i = 0 ; i< jfinalModel.getMethodModels().size() ; i++){ + codeTemplate.genMethodContent(jfinalModel.getMethodModels().get(i).getAccessType(), + jfinalModel.getMethodModels().get(i).getReturnType(), + jfinalModel.getMethodModels().get(i).getMethodName(), + jfinalModel.getMethodModels().get(i).getParamList(), + jfinalModel.getMethodModels().get(i).getFunctionBody(), + jfinalModel.getMethodModels().get(i).getHeadSpace(),model.isInterface(), + jfinalModel.getMethodModels().get(i).getAnnotations()); + } + return codeTemplate.end().toString(); + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodesCreator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodesCreator.java new file mode 100644 index 0000000..b1c33b7 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/creator/DefaultJfinalCodesCreator.java @@ -0,0 +1,95 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.creator; + +import java.util.List; + +import com.hyts.codegen.jfinal.base.BaseJfinalCreator; +import com.hyts.codegen.jfinal.model.JfinalBuildModel; + +/** + * @title DefaultJfinalCodesCreator.java + * @package com.hyts.codegen.jfinal.creator + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class DefaultJfinalCodesCreator implements + BaseJfinalCreator> { + + /* (非 Javadoc) + * TODO(方法功能的描述)- buildModel + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildModel(java.lang.Object) + * @exception + */ + + @Override + public String buildModel(List model) { + // TODO Auto-generated method stub + return null; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- buildDao + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildDao(java.lang.Object) + * @exception + */ + + @Override + public String buildDao(List model) { + // TODO Auto-generated method stub + return null; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- buildService + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildService(java.lang.Object) + * @exception + */ + + @Override + public String buildService(List model) { + // TODO Auto-generated method stub + return null; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- buildController + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @see com.hyts.codegen.jfinal.base.BaseJfinalWriter#buildController(java.lang.Object) + * @exception + */ + + @Override + public String buildController(List model) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/JfinalBuildModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/JfinalBuildModel.java new file mode 100644 index 0000000..42a12ed --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/JfinalBuildModel.java @@ -0,0 +1,488 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.model; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.hyts.codegen.base.JavaDocModel; +import com.hyts.codegen.base.JavaFieldModel; +import com.hyts.codegen.base.JavaMethodModel; +import com.hyts.codegen.base.JavaModel; +import com.hyts.codegen.base.JavaTypeModel; +import com.hyts.guava.String.Strings; +import com.hyts.guava.object.Objects; +import com.hyts.template.config.JavaTemplateConfig.JavaType; + +/** + * @title JfinalBuildModel.java + * @package com.hyts.codegen.jfinal.model + * @description Jfinal特定封装模型类:用于覆盖模型所需数据 + * @see JavaModel + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class JfinalBuildModel extends JavaModel{ + + + private SimpleBuildModel model; + + /** + * @constructor:JfinalBuildModel + * @param model + */ + public JfinalBuildModel(SimpleBuildModel model) { + Objects.checkNull(model); + this.setBasePackageName(Strings.compareBlankAndSet(model.getBasePackageName(),".")); + if(Objects.isNull(model.getJavaDocMap())){ + model.setJavaDocMap(new HashMap<>()); + model.getJavaDocMap().put("author","alex.libo"); + model.getJavaDocMap().put("description", "generate by coffice-toolbox-codegen"); + model.getJavaDocMap().put("date", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + } + this.model = model; + } + + /** + * initModel:初始化模型类 + *

初始化模型类:准备可以指定的数据信息

+ * @return + * @exception + */ + public JfinalBuildModel initModel(){ + //javaDoc模型构建 + JavaDocModel model = new JavaDocModel(this.model.getJavaDocMap(),""); + this.setDocModel(model); + this.setModelPackageName(this.model.getModelPackageName()); + //引入包信息 + this.setImportClasses(this.model.getImportClassName()); + if(Objects.isNull(this.getImportClasses())){ + this.setImportClasses(new String[]{"import com.jfinal.plugin.activerecord.Model"}); + }else { + String [] tempArray = new String[this.getImportClasses().length+1]; + tempArray[this.getImportClasses().length] = "import com.jfinal.plugin.activerecord.Model"; + System.arraycopy(this.getImportClasses(), 0,tempArray , 0, this.getImportClasses().length); + this.setImportClasses(tempArray); + } + //引入类信息 + JavaTypeModel model2 = new JavaTypeModel(); + model2.setAccessType("public"); + model2.setAnnotations(this.model.getAnnotations()); + model2.setClassName(this.model.getJavaTypeName()+" extends Model<"+this.model.getJavaTypeName()+">"); + model2.setJavaType(JavaType.TYPE); + this.setTypeModel(model2); + //初始化属性模型 + List fields = new LinkedList<>(); + JavaFieldModel model3 = new JavaFieldModel(); + model3.setHeadSpace(" "); + model3.setReturnType(this.model.getJavaTypeName()); + model3.setAccessType("public static final"); + model3.setFieldName(" DAO = new "+this.model.getJavaTypeName()+"()"); + fields.add(model3); + this.setFieldModels(fields); + return this; + } + + /** + * initDao + *

初始化数据访问层

+ * @return + * @exception + */ + public JfinalBuildModel initDao(){ + //javaDoc模型构建 + JavaDocModel model = new JavaDocModel(this.model.getJavaDocMap(),""); + this.setDocModel(model); + this.setModelPackageName(this.model.getModelPackageName()); + //引入包信息 + this.setImportClasses(this.model.getImportClassName()); + //暂时保留对model类的引用 + if(Objects.isNull(this.getImportClasses())){ + this.setImportClasses(new String[]{"import com.jfinal.plugin.activerecord.Model"}); + }else { + String [] tempArray = new String[this.getImportClasses().length+5]; + tempArray[this.getImportClasses().length] = "import com.jfinal.plugin.activerecord.Model"; + tempArray[this.getImportClasses().length+1] = "import com.hyts.jfmvc.scan.annotation.Repository"; + tempArray[this.getImportClasses().length+2] = "import com.jfinal.plugin.activerecord.Page"; + tempArray[this.getImportClasses().length+3] = "import com.jfinal.plugin.activerecord.TableMapping"; + tempArray[this.getImportClasses().length+4] = "import com.hyts.jfmvc.util.StringUtils"; + System.arraycopy(this.getImportClasses(), 0,tempArray , 0, this.getImportClasses().length); + this.setImportClasses(tempArray); + } + //引入类信息 + JavaTypeModel model2 = new JavaTypeModel(); + model2.setAccessType("public"); + model2.setAnnotations(this.model.getAnnotations()); + model2.setClassName(this.model.getJavaTypeName()); + model2.setJavaType(JavaType.TYPE); + this.setTypeModel(model2); + + //初始化方法模型 + List methods = new LinkedList<>(); + String beanClassName = this.getImportClasses()[0].substring(this.getImportClasses()[0].lastIndexOf(".")+1); + + //Query插入的方法 + JavaMethodModel queryMethod = new JavaMethodModel(); + queryMethod.setHeadSpace(" "); + queryMethod.setAccessType("public"); + StringBuilder sb = new StringBuilder(); + sb.append(String.format(" Set> params = %s._getAttrsEntrySet();\n",Strings.upperCamelToLowerCamel(beanClassName))); + sb.append(String.format(" String tableName = TableMapping.me().getTable(%s.getClass()).getName();\n",Strings.upperCamelToLowerCamel(beanClassName))); + sb.append(" StringBuilder sql = new StringBuilder(\"FROM \").append(tableName).append(\" WHERE 1 = 1 \");\n"); + sb.append(" List paramValues = new LinkedList();\n"); + sb.append(" for(Map.Entry param : params){\n"); + sb.append(" if(StringUtils.isNotEmpty(param.getKey()) && param.getValue() != null){\n"); + sb.append(" sql.append(\" AND \").append(param.getKey()).append(\" = ?\");\n"); + sb.append(" paramValues.add(param.getValue());\n"); + sb.append(" }\n"); + sb.append(" }\n"); + sb.append(String.format(" return %s.DAO.paginate(pageNum,pageSize,\"SELECT *\",sql.toString(),paramValues.toArray(new Object[paramValues.size()]));\n",beanClassName)); + queryMethod.setFunctionBody(sb.toString()); + queryMethod.setMethodName("query"); + queryMethod.setReturnType(String.format("Page<%s>",beanClassName)); + Map paramList = Maps.newTreeMap(); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + paramList.put("byte","pageSize"); + paramList.put("int","pageNum"); + queryMethod.setParamList(paramList); + methods.add(queryMethod); + + //Insert插入的方法 + JavaMethodModel insertMethod = new JavaMethodModel(); + insertMethod.setHeadSpace(" "); + insertMethod.setAccessType("public"); + insertMethod.setFunctionBody(" return "+String.format(beanClassName+".DAO._setAttrs(%s).save();\n",Strings.upperCamelToLowerCamel(beanClassName))); + insertMethod.setMethodName("insert"); + insertMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + insertMethod.setParamList(paramList); + methods.add(insertMethod); + + //Delete删除的方法 + JavaMethodModel deleteMethod = new JavaMethodModel(); + deleteMethod.setHeadSpace(" "); + deleteMethod.setAccessType("public"); + deleteMethod.setFunctionBody(" return "+beanClassName+".DAO.deleteById(idValues);\n"); + deleteMethod.setMethodName("delete"); + deleteMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put("Object...","idValues"); + deleteMethod.setParamList(paramList); + methods.add(deleteMethod); + + //Update更新的方法 + JavaMethodModel updateMethod = new JavaMethodModel(); + updateMethod.setHeadSpace(" "); + updateMethod.setAccessType("public"); + updateMethod.setFunctionBody(" return "+String.format(beanClassName+".DAO._setAttrs(%s).update();\n",Strings.upperCamelToLowerCamel(beanClassName))); + updateMethod.setMethodName("update"); + updateMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + updateMethod.setParamList(paramList); + methods.add(updateMethod); + + //Load加载信息方法 + JavaMethodModel loadMethod = new JavaMethodModel(); + loadMethod.setHeadSpace(" "); + loadMethod.setAccessType("public"); + loadMethod.setFunctionBody(" return "+beanClassName+".DAO.findById(id);\n"); + loadMethod.setMethodName("load"); + loadMethod.setReturnType(beanClassName); + paramList = Maps.newHashMap(); + paramList.put("Object","id"); + loadMethod.setParamList(paramList); + methods.add(loadMethod); + + this.setMethodModels(methods); + return this; + } + + + /** + * initService + *

初始化业务逻辑层

+ * @return + * @exception + */ + public JfinalBuildModel initService(boolean isInterface) { + //javaDoc模型构建 + JavaDocModel model = new JavaDocModel(this.model.getJavaDocMap(), ""); + this.setDocModel(model); + this.setModelPackageName(this.model.getModelPackageName()); + //引入包信息 + this.setImportClasses(this.model.getImportClassName()); + //暂时保留对model类的引用 + String[] tempArray = null; + if (Objects.isNull(this.getImportClasses())) { + this.setImportClasses(new String[]{"import com.jfinal.plugin.activerecord.Model"}); + } else { + if (isInterface) { + tempArray = new String[this.getImportClasses().length + 1]; + tempArray[this.getImportClasses().length] = "import com.jfinal.plugin.activerecord.Page"; + } else { + tempArray = new String[this.getImportClasses().length + 3]; + tempArray[this.getImportClasses().length] = "import com.jfinal.plugin.activerecord.Page"; + tempArray[this.getImportClasses().length + 1] = "import com.hyts.jfmvc.scan.annotation.Resource"; + tempArray[this.getImportClasses().length + 2] = "import com.hyts.jfmvc.scan.annotation.Service"; + } + System.arraycopy(this.getImportClasses(), 0, tempArray, 0, this.getImportClasses().length); + this.setImportClasses(tempArray); + } + //引入类信息 + JavaTypeModel model2 = new JavaTypeModel(); + model2.setAccessType("public"); + model2.setAnnotations(this.model.getAnnotations()); + if (isInterface){ + model2.setJavaType(JavaType.INTERFACE); + model2.setClassName(this.model.getJavaTypeName()); + }else{ + model2.setJavaType(JavaType.TYPE); + String interfaceName = tempArray[1].substring(tempArray[1].lastIndexOf(".")+1);//this.model.getJavaTypeName().substring(0, this.model.getJavaTypeName().lastIndexOf("Impl")); + model2.setClassName(isInterface ? this.model.getJavaTypeName() : this.model.getJavaTypeName() + " implements " + interfaceName); + JavaFieldModel fieldModel = new JavaFieldModel(); + fieldModel.setHeadSpace(" "); + fieldModel.setAccessType("public"); + fieldModel.setFieldName("dao"); + fieldModel.setReturnType(tempArray[2].substring(tempArray[2].lastIndexOf(".")+1)); + fieldModel.setAnnotations(new String[]{"Resource"}); + this.setFieldModels(new ArrayList(){{ + add(fieldModel); + }}); + } + this.setTypeModel(model2); + //初始化方法模型 + List methods = new LinkedList<>(); + String beanClassName = this.getImportClasses()[0].substring(this.getImportClasses()[0].lastIndexOf(".")+1); + + //Query插入的方法 + JavaMethodModel queryMethod = new JavaMethodModel(); + queryMethod.setHeadSpace(" "); + String functionBody = " return dao.query(%s,pageSize,pageNum);\n"; + queryMethod.setFunctionBody(isInterface?"":String.format(functionBody,Strings.upperCamelToLowerCamel(beanClassName))); + queryMethod.setMethodName("query"); + queryMethod.setReturnType(String.format("Page<%s>",beanClassName)); + Map paramList = Maps.newTreeMap(); + paramList.put("byte","pageSize"); + paramList.put("int","pageNum"); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + queryMethod.setParamList(paramList); + methods.add(queryMethod); + + //Insert插入的方法 + JavaMethodModel insertMethod = new JavaMethodModel(); + insertMethod.setHeadSpace(" "); + functionBody = String.format(" return dao.insert(%s);\n",Strings.upperCamelToLowerCamel(beanClassName)); + insertMethod.setFunctionBody(isInterface?"":functionBody); + insertMethod.setMethodName("insertData"); + insertMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + insertMethod.setParamList(paramList); + methods.add(insertMethod); + + //Delete删除的方法 + JavaMethodModel deleteMethod = new JavaMethodModel(); + deleteMethod.setHeadSpace(" "); + functionBody = " return dao.delete(idValues);\n"; + deleteMethod.setFunctionBody(isInterface?"":functionBody); + deleteMethod.setMethodName("deleteData"); + deleteMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put("Object...","idValues"); + deleteMethod.setParamList(paramList); + methods.add(deleteMethod); + + //Update更新的方法 + JavaMethodModel updateMethod = new JavaMethodModel(); + updateMethod.setHeadSpace(" "); + functionBody = " return dao.update(%s);\n"; + updateMethod.setFunctionBody(isInterface?"":String.format(functionBody,Strings.upperCamelToLowerCamel(beanClassName))); + updateMethod.setMethodName("updateData"); + updateMethod.setReturnType("boolean"); + paramList = Maps.newHashMap(); + paramList.put(beanClassName,Strings.upperCamelToLowerCamel(beanClassName)); + updateMethod.setParamList(paramList); + methods.add(updateMethod); + + //Load加载信息方法 + JavaMethodModel loadMethod = new JavaMethodModel(); + loadMethod.setHeadSpace(" "); + functionBody = " return dao.load(id);\n"; + loadMethod.setMethodName("loadData"); + loadMethod.setFunctionBody(isInterface?"":functionBody); + loadMethod.setReturnType(beanClassName); + paramList = Maps.newHashMap(); + paramList.put("Object","id"); + loadMethod.setParamList(paramList); + methods.add(loadMethod); + + this.setMethodModels(methods); + return this; + } + + /** + * initController + *

初始化访问控制层

+ * @return + * @exception + */ + public JfinalBuildModel initController() { + //javaDoc模型构建 + JavaDocModel model = new JavaDocModel(this.model.getJavaDocMap(), ""); + this.setDocModel(model); + this.setModelPackageName(this.model.getModelPackageName()); + //引入包信息 + this.setImportClasses(this.model.getImportClassName()); + //暂时保留对model类的引用 + String[] tempArray = null; + if (Objects.isNull(this.getImportClasses())) { + this.setImportClasses(new String[]{"import com.jfinal.plugin.activerecord.Model"}); + } else { + tempArray = new String[this.getImportClasses().length + 5]; + tempArray[this.getImportClasses().length] = "import com.jfinal.plugin.activerecord.Page"; + tempArray[this.getImportClasses().length + 1] = "import com.hyts.jfmvc.scan.annotation.Resource"; + tempArray[this.getImportClasses().length + 2] = "import com.hyts.jfmvc.scan.annotation.Service"; + tempArray[this.getImportClasses().length + 3] = "import com.hyts.jfmvc.scan.annotation.Controller"; + tempArray[this.getImportClasses().length + 4] = "import com.hyts.jfmvc.web.controller.BaseController"; + System.arraycopy(this.getImportClasses(), 0, tempArray, 0, this.getImportClasses().length); + this.setImportClasses(tempArray); + } + //引入类信息 + JavaTypeModel model2 = new JavaTypeModel(); + model2.setAccessType("public"); + model2.setAnnotations(this.model.getAnnotations()); + model2.setJavaType(JavaType.TYPE); + model2.setClassName(this.model.getJavaTypeName()+" extends BaseController"); + JavaFieldModel fieldModel = new JavaFieldModel(); + fieldModel.setHeadSpace(" "); + fieldModel.setAccessType("public"); + fieldModel.setFieldName("service"); + fieldModel.setReturnType(tempArray[1].substring(tempArray[1].lastIndexOf(".")+1)); + fieldModel.setAnnotations(new String[]{"Resource"}); + this.setFieldModels(new ArrayList(){{ + add(fieldModel); + }}); + this.setTypeModel(model2); + //初始化方法模型 + List methods = new LinkedList<>(); + String beanClassName = this.getImportClasses()[0].substring(this.getImportClasses()[0].lastIndexOf(".")+1); + + //Query插入的方法 + JavaMethodModel indexMethod = new JavaMethodModel(); + indexMethod.setHeadSpace(" "); + String functionBody = " render(\"index\");\n"; + indexMethod.setFunctionBody(functionBody); + indexMethod.setMethodName("index"); + indexMethod.setReturnType("void"); + methods.add(indexMethod); + + //Query插入的方法 + JavaMethodModel queryMethod = new JavaMethodModel(); + queryMethod.setHeadSpace(" "); + StringBuilder functionBodyAppend = new StringBuilder(" JSON(Operation.QUERY, service.query(this.getModel(%s.class,true),this.getPageSize(),this.getPageNum()).getList());\n"); + queryMethod.setFunctionBody(String.format(functionBodyAppend.toString(),beanClassName)); + queryMethod.setMethodName("queryForList"); + queryMethod.setReturnType("void"); + methods.add(queryMethod); + + //Insert插入的方法-01 + JavaMethodModel addForModelPage = new JavaMethodModel(); + addForModelPage.setHeadSpace(" "); + functionBodyAppend = new StringBuilder(" render(\"addForModel\");\n"); + addForModelPage.setFunctionBody(String.format(functionBodyAppend.toString(),beanClassName)); + addForModelPage.setMethodName("addForModelPage"); + addForModelPage.setReturnType("void"); + methods.add(addForModelPage); + + //Insert插入方法-02 + JavaMethodModel addForModel = new JavaMethodModel(); + addForModel.setHeadSpace(" "); + functionBodyAppend = new StringBuilder(String.format(" JSON(Operation.ADD,service.insertData(this.getModel(%s.class,true)));\n",beanClassName)); + addForModel.setFunctionBody(String.format(functionBodyAppend.toString(),beanClassName)); + addForModel.setMethodName("addForModel"); + addForModel.setReturnType("void"); + methods.add(addForModel); + + //Delete删除的方法 + JavaMethodModel deleteMethod = new JavaMethodModel(); + deleteMethod.setHeadSpace(" "); + functionBody = " JSON(Operation.DELETE,service.deleteData(this.getPara(DEFAULT_IDENTIFIED_TOKEN)));\n"; + deleteMethod.setFunctionBody(functionBody); + deleteMethod.setMethodName("removeForModel"); + deleteMethod.setReturnType("void"); + methods.add(deleteMethod); + + + //Update更新的方法-01 + JavaMethodModel editForModelPage = new JavaMethodModel(); + editForModelPage.setHeadSpace(" "); + functionBody = " render(\"editForModel\");\n"; + editForModelPage.setFunctionBody(functionBody); + editForModelPage.setMethodName("editForModelPage"); + editForModelPage.setReturnType("void"); + methods.add(editForModelPage); + + //Update更新的方法-02 + JavaMethodModel updateMethod = new JavaMethodModel(); + updateMethod.setHeadSpace(" "); + functionBody = " JSON(Operation.EDIT,service.updateData(this.getModel(%s.class,true)));\n"; + updateMethod.setFunctionBody(String.format(functionBody,beanClassName)); + updateMethod.setMethodName("editForModel"); + updateMethod.setReturnType("void"); + methods.add(updateMethod); + + + //Load加载信息方法 + JavaMethodModel loadMethod = new JavaMethodModel(); + loadMethod.setHeadSpace(" "); + functionBody = " JSON(Operation.LOAD,service.loadData(this.getPara(DEFAULT_IDENTIFIED_TOKEN)));\n"; + loadMethod.setMethodName("loadForModel"); + loadMethod.setFunctionBody(functionBody); + loadMethod.setReturnType("void"); + methods.add(loadMethod); + + this.setMethodModels(methods); + return this; + } + + /** + * @name model's getter method + * @return model + */ + public SimpleBuildModel getModel() { + return model; + } + + /** + * @name model's setter method + * @param model + * @return void + */ + public void setModel(SimpleBuildModel model) { + this.model = model; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/SimpleBuildModel.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/SimpleBuildModel.java new file mode 100644 index 0000000..55398e2 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/model/SimpleBuildModel.java @@ -0,0 +1,299 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.model; + +import java.util.Map; + +import com.hyts.codegen.jfinal.config.JfinalParamConfig; + +/** + * @title SimpleBuildModel.java + * @package com.hyts.codegen.jfinal.model + * @description 提供用户使用的构建模型参数 + * @see JfinalParamConfig + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public class SimpleBuildModel extends JfinalParamConfig { + + + /** + *

基础包类

+ * @fieldName basePackageName + * @fieldType String + */ + private String basePackageName; + + + /** + *

模型包名称

+ * @fieldName modelPackageName + * @fieldType String + */ + private String modelPackageName; + + /** + *

注释集合

+ * @fieldName annotationMap + * @fieldType Map + */ + private Map javaDocMap; + + /** + *

引入class类名称集合

+ * @fieldName importClassName + * @fieldType String[] + */ + String[] importClassName; + + /** + *

类名称信息

+ * @fieldName javaTypeName + * @fieldType String + */ + String javaTypeName; + + /** + *

{字段的描述}

+ * @fieldName annotations + * @fieldType String[] + */ + String[] annotations; + + + /** + *

外部文件属性

+ * @fieldName externalFilePath + * @fieldType String + */ + String externalFilePath; + + /** + * @name basePackageName's getter method + * @return basePackageName + */ + public String getBasePackageName() { + return basePackageName; + } + + /** + * @name basePackageName's setter method + * @param basePackageName + * @return void + */ + public void setBasePackageName(String basePackageName) { + this.basePackageName = basePackageName; + } + + /** + * @name modelPackageName's getter method + * @return modelPackageName + */ + public String getModelPackageName() { + return modelPackageName; + } + + /** + * @name modelPackageName's setter method + * @param modelPackageName + * @return void + */ + public void setModelPackageName(String modelPackageName) { + this.modelPackageName = modelPackageName; + } + + /** + * @name javaDocMap's getter method + * @param none + * @return javaDocMap + */ + public Map getJavaDocMap() { + return javaDocMap; + } + + /** + * @name javaDocMap's setter method + * @param javaDocMap + * @return void + */ + public void setJavaDocMap(Map javaDocMap) { + this.javaDocMap = javaDocMap; + } + + /** + * @constructor:SimpleBuildModel + * @param basePackageName + * @param modelPackageName + * @param javaDocMap + */ + public SimpleBuildModel(String basePackageName, String modelPackageName, + Map javaDocMap) { + super(); + this.basePackageName = basePackageName; + this.modelPackageName = modelPackageName; + this.javaDocMap = javaDocMap; + } + + /** + * @constructor:SimpleBuildModel + * @param basePackageName + * @param modelPackageName + */ + + public SimpleBuildModel(String basePackageName, String modelPackageName) { + super(); + this.basePackageName = basePackageName; + this.modelPackageName = modelPackageName; + } + + /** + * @name importClassName's getter method + * @param none + * @return importClassName + */ + public String[] getImportClassName() { + return importClassName; + } + + /** + * @name importClassName's setter method + * @param importClassName + * @return void + */ + public void setImportClassName(String[] importClassName) { + this.importClassName = importClassName; + } + + /** + * @name javaTypeName's getter method + * @param none + * @return javaTypeName + */ + public String getJavaTypeName() { + return javaTypeName; + } + + /** + * @name javaTypeName's setter method + * @param javaTypeName + * @return void + */ + public void setJavaTypeName(String javaTypeName) { + this.javaTypeName = javaTypeName; + } + + /** + * @constructor:SimpleBuildModel + * @param basePackageName + * @param modelPackageName + * @param javaDocMap + * @param importClassName + * @param javaTypeName + */ + + + public SimpleBuildModel(String basePackageName, String modelPackageName, + Map javaDocMap, String[] importClassName, + String javaTypeName) { + super(); + this.basePackageName = basePackageName; + this.modelPackageName = modelPackageName; + this.javaDocMap = javaDocMap; + this.importClassName = importClassName; + this.javaTypeName = javaTypeName; + } + + /** + * @constructor:SimpleBuildModel + * @param basePackageName + * @param modelPackageName + * @param javaDocMap + * @param javaTypeName + */ + + + public SimpleBuildModel(String basePackageName, String modelPackageName, + Map javaDocMap, String javaTypeName) { + super(); + this.basePackageName = basePackageName; + this.modelPackageName = modelPackageName; + this.javaDocMap = javaDocMap; + this.javaTypeName = javaTypeName; + } + + /** + * @name annotations's getter method + * @param none + * @return annotations + */ + public String[] getAnnotations() { + return annotations; + } + + /** + * @name annotations's setter method + * @param annotations + * @return void + */ + public void setAnnotations(String[] annotations) { + this.annotations = annotations; + } + + /** + * @name externalFilePath's getter method + * @param none + * @return externalFilePath + */ + public String getExternalFilePath() { + return externalFilePath; + } + + /** + * @name externalFilePath's setter method + * @param externalFilePath + * @return void + */ + public void setExternalFilePath(String externalFilePath) { + this.externalFilePath = externalFilePath; + } + + /** + * @constructor:SimpleBuildModel + */ + public SimpleBuildModel() { + super(); + } + + /** + * @constructor:SimpleBuildModel + * @param basePackageName + */ + public SimpleBuildModel(String basePackageName) { + super(); + this.basePackageName = basePackageName; + } + + private boolean isInterface; + + public boolean isInterface() { + return isInterface; + } + + public void setInterface(boolean anInterface) { + isInterface = anInterface; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/BaseJfinalWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/BaseJfinalWriter.java new file mode 100644 index 0000000..b16c1ef --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/BaseJfinalWriter.java @@ -0,0 +1,67 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.writer; + +/** + * @title BaseJfinalWriter.java + * @package com.hyts.codegen.jfinal.writer + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月12日 + * @version V1.0 + */ +public interface BaseJfinalWriter { + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildModel(JfinalBuildModel model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildDAO(JfinalBuildModel model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildService(JfinalBuildModel model); + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param model + * @return + * @exception + */ + String buildController(JfinalBuildModel model); + + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JFinalWriterConfig.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JFinalWriterConfig.java new file mode 100644 index 0000000..837618e --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JFinalWriterConfig.java @@ -0,0 +1,41 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.writer; + +import java.io.File; + +import com.hyts.guava.String.Strings; + +/** + * @title JFinalWriterConfig.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JFinalWriterConfig { + + /** + *

JFINAL_MAVEN_BASE_PATH:JFINAL-MAVEN基础项目路径

+ * @fieldName JFINAL_MAVEN_BASE_PATH + * @fieldType String + */ + public static final String JFINAL_MAVEN_BASE_PATH = + System.getProperty("user.dir")+File.separator+Strings.join(new String[]{"src","main","java"},File.separator)+File.separator; + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JavaCodeWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JavaCodeWriter.java new file mode 100644 index 0000000..b2388f1 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JavaCodeWriter.java @@ -0,0 +1,120 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.writer; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import com.alibaba.fastjson.util.IOUtils; +import com.google.common.base.Charsets; +import com.hyts.codegen.base.AbstractFileWriter; +import com.hyts.codegen.jfinal.config.JavaWriterConfig; +import com.hyts.guava.exception.Exceptions; +import com.hyts.guava.object.Objects; +import com.hyts.logger.factory.LoggerFactory; +import com.hyts.template.common.BaseJavaFileTemplate; +import com.hyts.template.strformat.JavaCodeTemplate; + +/** + * @title FileWriterHandler.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JavaCodeWriter implements AbstractFileWriter{ + + /** + *

日志输出器}

+ * @fieldName logger + * @fieldType Logger + */ + private static Logger logger = LoggerFactory.getLogger(JavaCodeWriter.class); + + + + /* (非 Javadoc) + * @param classpath + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerInternal(String classpath, String object) { + Objects.checkNull(classpath);Objects.checkNull(object); + String url = JavaWriterConfig.JFINAL_MAVEN_BASE_PATH + + classpath.replace("/",File.separator); + Path filePath = Paths.get(url); + logger.info("【coffice-toolbox-codegen】- 生成文件路径文件:"+url); + File parentFile = filePath.getParent().toFile(); + if(!filePath.getParent().toFile().exists()){ + parentFile.mkdirs(); + } + BufferedWriter writer = null; + try{ + Files.deleteIfExists(filePath); + Files.createFile(filePath); + writer = Files.newBufferedWriter(filePath, Charsets.UTF_8, LinkOption.NOFOLLOW_LINKS); + writer.write(object); + } catch (IOException e) { + Exceptions.throwRuntimeException(e); + } finally{ + IOUtils.close(writer); + } + return filePath.toString(); + } + + /* (非 Javadoc) + * @param outputFile + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, String object) { + // TODO Auto-generated method stub + return null; + } + + public static void main(String[] args) { + BaseJavaFileTemplate tempate = new JavaCodeTemplate(); + tempate.genPackageContent("com.hyts.codegen", new String[]{"test"}); + tempate.genImportContent(new String[]{"import java.util.Map;","import java.util.logging.Logger;"}); + Map annotationMap = new HashMap<>(); + annotationMap.put("author","alex/libo"); + annotationMap.put("date","20180509"); + annotationMap.put("description","om.hyts.codegen.generator.AbstractFileWriter#writerEx"); + tempate.genJavaDocContent(annotationMap,""); + tempate.genTypeContent(null, null, "test", null); + tempate.genFieldContent(null, "String", "name", " ", null); + new JavaCodeWriter().writerInternal("com/hyts/codegen/test/test.java",tempate.end().toString()); + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JfinalCodeWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JfinalCodeWriter.java new file mode 100644 index 0000000..2f2addf --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/jfinal/writer/JfinalCodeWriter.java @@ -0,0 +1,119 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.jfinal.writer; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import com.alibaba.fastjson.util.IOUtils; +import com.google.common.base.Charsets; +import com.hyts.codegen.base.AbstractFileWriter; +import com.hyts.codegen.jfinal.config.JFinalWriterConfig; +import com.hyts.guava.exception.Exceptions; +import com.hyts.guava.object.Objects; +import com.hyts.logger.factory.LoggerFactory; +import com.hyts.template.common.BaseJavaFileTemplate; +import com.hyts.template.strformat.JavaCodeTemplate; + +/** + * @title FileWriterHandler.java + * @package com.hyts.codegen.jfinal.common + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月10日 + * @version V1.0 + */ +public final class JfinalCodeWriter implements AbstractFileWriter{ + + /** + *

日志输出器}

+ * @fieldName logger + * @fieldType Logger + */ + private static Logger logger = LoggerFactory.getLogger(JavaCodeWriter.class); + + + /* (非 Javadoc) + * @param classpath + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerInternal(String classpath, String object) { + Objects.checkNull(classpath);Objects.checkNull(object); + String url = JFinalWriterConfig.JFINAL_MAVEN_BASE_PATH + + classpath.replace("/",File.separator); + Path filePath = Paths.get(url); + logger.info("【coffice-toolbox-codegen】- 生成文件路径文件:"+url); + File parentFile = filePath.getParent().toFile(); + if(!filePath.getParent().toFile().exists()){ + parentFile.mkdirs(); + } + BufferedWriter writer = null; + try{ + Files.deleteIfExists(filePath); + Files.createFile(filePath); + writer = Files.newBufferedWriter(filePath, Charsets.UTF_8, LinkOption.NOFOLLOW_LINKS); + writer.write(object); + } catch (IOException e) { + Exceptions.throwRuntimeException(e); + } finally{ + IOUtils.close(writer); + } + return filePath.toString(); + } + + /* (非 Javadoc) + * @param outputFile + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, String object) { + // TODO Auto-generated method stub + return null; + } + + public static void main(String[] args) { + BaseJavaFileTemplate tempate = new JavaCodeTemplate(); + tempate.genPackageContent("com.hyts.codegen", new String[]{"test"}); + tempate.genImportContent(new String[]{"import java.util.Map;","import java.util.logging.Logger;"}); + Map annotationMap = new HashMap<>(); + annotationMap.put("author","alex/libo"); + annotationMap.put("date","20180509"); + annotationMap.put("description","om.hyts.codegen.generator.AbstractFileWriter#writerEx"); + tempate.genJavaDocContent(annotationMap,""); + tempate.genTypeContent(null, null, "test", null); + tempate.genFieldContent(null, "String", "name", " ", null); + new JavaCodeWriter().writerInternal("com/hyts/codegen/test/test.java",tempate.end().toString()); + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/MybatisGenerator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/MybatisGenerator.java new file mode 100644 index 0000000..b3f4c1c --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/MybatisGenerator.java @@ -0,0 +1,61 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.mybatis; + +import org.mybatis.generator.api.ShellRunner; + +/** + * @title MybatisGenerator.java + * @package org.mybatis.generator + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月27日 + * @version V1.0 + */ +public class MybatisGenerator { + + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @param generatorConfigPath + * @exception + */ + public static void generate(String generatorConfigPath) { + String[] args = new String[] {"-configfile",generatorConfigPath,"-overwrite"}; + ShellRunner.main(args); + System.out.println("生成代码结束!"); + } + + /** + * TODO(方法功能的描述) + *

TODO(这里用一句话描述这个方法的作用)

+ * @exception + */ + public static void generate() { + String[] args = new String[] {"-configfile","src/main/resources/generatorConfig.xml","-overwrite"}; + ShellRunner.main(args); + System.out.println("生成代码结束!"); + } + + public static void main(String[] args) { + generate(); + } + + + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/comment/CodeCommentGenerator.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/comment/CodeCommentGenerator.java new file mode 100644 index 0000000..6ce59e2 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/comment/CodeCommentGenerator.java @@ -0,0 +1,300 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.mybatis.comment; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; + +import javax.xml.bind.annotation.XmlElement; +import static org.mybatis.generator.internal.util.StringUtility.isTrue; +import org.mybatis.generator.api.CommentGenerator; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.InnerClass; +import org.mybatis.generator.api.dom.java.InnerEnum; +import org.mybatis.generator.api.dom.java.JavaElement; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.config.MergeConstants; +import org.mybatis.generator.config.PropertyRegistry; + +/** + * @title CodeCommentGenerator.java + * @package com.hyts.gencode.comment + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年4月26日 + * @version V1.0 + */ +public class CodeCommentGenerator implements CommentGenerator{ + + + private Properties properties; + private Properties systemPro; + private boolean suppressDate; + private boolean suppressAllComments; + private String currentDateStr; + + public CodeCommentGenerator() { + super(); + properties = new Properties(); + systemPro = System.getProperties(); + suppressDate = false; + suppressAllComments = false; + currentDateStr = (new SimpleDateFormat("yyyy-MM-dd")).format(new Date()); + } + + public void addJavaFileComment(CompilationUnit compilationUnit) { + return; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- addComment + *

TODO(这里用一句话描述这个方法的作用)

+ * @param arg0 + * @see org.mybatis.generator.api.CommentGenerator#addComment(org.mybatis.generator.api.dom.xml.XmlElement) + * @exception + */ + + @Override + public void addComment(org.mybatis.generator.api.dom.xml.XmlElement arg0) { + + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- addRootComment + *

TODO(这里用一句话描述这个方法的作用)

+ * @param arg0 + * @see org.mybatis.generator.api.CommentGenerator#addRootComment(org.mybatis.generator.api.dom.xml.XmlElement) + * @exception + */ + + @Override + public void addRootComment(org.mybatis.generator.api.dom.xml.XmlElement arg0) { + // TODO Auto-generated method stub + + } + + + public void addConfigurationProperties(Properties properties) { + this.properties.putAll(properties); + + suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE)); + + suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS)); + } + + /** + * This method adds the custom javadoc tag for. You may do nothing if you do + * not wish to include the Javadoc tag - however, if you do not include the + * Javadoc tag then the Java merge capability of the eclipse plugin will + * break. + * + * @param javaElement + * the java element + */ + protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { + javaElement.addJavaDocLine(" *"); + StringBuilder sb = new StringBuilder(); + sb.append(" * "); + sb.append(MergeConstants.NEW_ELEMENT_TAG); + if (markAsDoNotDelete) { + sb.append(" do_not_delete_during_merge"); + } + String s = getDateString(); + if (s != null) { + sb.append(' '); + sb.append(s); + } + javaElement.addJavaDocLine(sb.toString()); + } + + /** + * This method returns a formated date string to include in the Javadoc tag + * and XML comments. You may return null if you do not want the date in + * these documentation elements. + * + * @return a string representing the current timestamp, or null + */ + protected String getDateString() { + String result = null; + if (!suppressDate) { + result = currentDateStr; + } + return result; + } + + public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + innerClass.addJavaDocLine("/**"); + sb.append(" * "); + sb.append(introspectedTable.getFullyQualifiedTable()); + innerClass.addJavaDocLine(sb.toString().replace("\n", " ")); + sb.setLength(0); + sb.append(" * @author "); + sb.append(systemPro.getProperty("user.name")); + sb.append(" "); + sb.append(currentDateStr); + innerClass.addJavaDocLine(" */"); + } + + public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + innerEnum.addJavaDocLine("/**"); + sb.append(" * "); + sb.append(introspectedTable.getFullyQualifiedTable()); + innerEnum.addJavaDocLine(sb.toString().replace("\n", " ")); + innerEnum.addJavaDocLine(" */"); + } + + public void addFieldComment(Field field, IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + field.addJavaDocLine("/**"); + sb.append(" * "); + sb.append("@fieldName ").append(field.getName()).append("\r").append("\t"); + sb.append(" * ").append("@fieldType ").append(field.getType()); + sb.append(introspectedColumn.getRemarks()); + field.addJavaDocLine(sb.toString().replace("\n", " ")); + field.addJavaDocLine(" */"); + } + + public void addFieldComment(Field field, IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + field.addJavaDocLine("/**"); + sb.append(" * "); + sb.append("@fieldName ").append(field.getName()).append("\r").append("\t"); + sb.append(" * ").append("@fieldType ").append(field.getType()); + //sb.append(introspectedTable.getRemarks()); + field.addJavaDocLine(sb.toString().replace("\n", " ")); + field.addJavaDocLine(" */"); + } + + public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + method.addJavaDocLine("/**"); + sb.append(" * "); + sb.append("").append(method.getName()).append("\r").append("\t"); + sb.append(" * ").append("@return ").append(method.getReturnType()); + //sb.append(introspectedTable.getRemarks()); + method.addJavaDocLine(sb.toString().replace("\n", " ")); + method.addJavaDocLine(" */"); + } + + public void addGetterComment(Method method, IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + method.addJavaDocLine("/**"); + StringBuilder sb = new StringBuilder(); + sb.append(" * "); + sb.append(introspectedColumn.getRemarks()); + method.addJavaDocLine(sb.toString().replace("\n", " ")); + sb.setLength(0); + sb.append(" * @return "); + sb.append(introspectedColumn.getActualColumnName()); + sb.append(" "); + sb.append(introspectedColumn.getRemarks()); + method.addJavaDocLine(sb.toString().replace("\n", " ")); + method.addJavaDocLine(" */"); + } + + public void addSetterComment(Method method, IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + method.addJavaDocLine("/**"); + StringBuilder sb = new StringBuilder(); + sb.append(" * "); + sb.append(introspectedColumn.getRemarks()); + method.addJavaDocLine(sb.toString().replace("\n", " ")); + Parameter parm = method.getParameters().get(0); + sb.setLength(0); + sb.append(" * @param "); + sb.append(parm.getName()); + sb.append(" "); + sb.append(introspectedColumn.getRemarks()); + method.addJavaDocLine(sb.toString().replace("\n", " ")); + method.addJavaDocLine(" */"); + } + + public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + innerClass.addJavaDocLine("/**"); + sb.append(" * "); + sb.append(introspectedTable.getFullyQualifiedTable()); + innerClass.addJavaDocLine(sb.toString().replace("\n", " ")); + sb.setLength(0); + sb.append(" * @author "); + sb.append(systemPro.getProperty("user.name")); + sb.append(" "); + sb.append(currentDateStr); + innerClass.addJavaDocLine(" */"); + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- addModelClassComment + *

TODO(这里用一句话描述这个方法的作用)

+ * @param arg0 + * @param arg1 + * @see org.mybatis.generator.api.CommentGenerator#addModelClassComment(org.mybatis.generator.api.dom.java.TopLevelClass, org.mybatis.generator.api.IntrospectedTable) + * @exception + */ + + //@Override + public void addModelClassComment(TopLevelClass arg0, IntrospectedTable arg1) { + if (suppressAllComments) { + return; + } + StringBuilder sb = new StringBuilder(); + arg0.addJavaDocLine("/**"); + sb.append(" * "); + sb.append(arg1.getFullyQualifiedTable()); + arg0.addJavaDocLine(sb.toString().replace("\n", " ")); + sb.setLength(0); + sb.append(" * @author "); + sb.append(systemPro.getProperty("user.name")); + sb.append(" "); + sb.append(currentDateStr); + arg0.addJavaDocLine(" */"); + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisCodeWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisCodeWriter.java new file mode 100644 index 0000000..a2636b8 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisCodeWriter.java @@ -0,0 +1,63 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.mybatis.writer; + +import com.hyts.codegen.base.AbstractFileWriter; + +/** + * @title MybatisWriter.java + * @package com.hyts.codegen.mybatis.writer + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月11日 + * @version V1.0 + */ +public class MybatisCodeWriter implements AbstractFileWriter{ + + /* (非 Javadoc) + * TODO(方法功能的描述)- writerInternal + *

TODO(这里用一句话描述这个方法的作用)

+ * @param classpath + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerInternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerInternal(String classpath, Object object) { + // TODO Auto-generated method stub + return null; + } + + /* (非 Javadoc) + * TODO(方法功能的描述)- writerExternal + *

TODO(这里用一句话描述这个方法的作用)

+ * @param outputFile + * @param object + * @return + * @see com.hyts.codegen.generator.AbstractFileWriter#writerExternal(java.lang.String, java.lang.Object) + * @exception + */ + + @Override + public String writerExternal(String outputFile, Object object) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisWriter.java b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisWriter.java new file mode 100644 index 0000000..7912256 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/com/hyts/codegen/mybatis/writer/MybatisWriter.java @@ -0,0 +1,29 @@ +/* + * Copyright [2018] [Alex/libo(liboms@hotmail.com)] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.hyts.codegen.mybatis.writer; + +/** + * @title MybatisWriter.java + * @package com.hyts.codegen.mybatis.writer + * @description TODO + * @see TODO + * @author libo/Alex + * @email liboms@hotmail.com/liboware@163.com + * @date 2018年5月11日 + * @version V1.0 + */ +public class MybatisWriter { + +} diff --git a/coffice-toolbox-codegen/src/main/java/org/.svn/entries b/coffice-toolbox-codegen/src/main/java/org/.svn/entries new file mode 100644 index 0000000..afceb36 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/.svn/entries @@ -0,0 +1,31 @@ +10 + +dir +8392 +svn://10.10.55.44/Cfae_PPN/truck/01%20%E5%BC%80%E5%8F%91%E5%BA%93/%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91/D04_CODE/fans/mybatis_gen/src/org +svn://10.10.55.44/Cfae_PPN + + + +2016-06-20T02:45:04.445808Z +416 +wanghongbo + + +svn:special svn:externals svn:needs-lock + + + + + + + + + + + +9f9541a1-e8dd-4926-b0f6-dcf5f8f9e496 + +mybatis +dir + diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/CommentGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/CommentGenerator.java new file mode 100644 index 0000000..c86a82a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/CommentGenerator.java @@ -0,0 +1,122 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import java.util.Properties; + +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.InnerClass; +import org.mybatis.generator.api.dom.java.InnerEnum; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * Implementations of this interface are used to generate comments for the + * various artifacts. + * + * @author Jeff Butler + */ +public interface CommentGenerator { + + /** + * Adds properties for this instance from any properties configured in the + * CommentGenerator configuration. + * + * This method will be called before any of the other methods. + * + * @param properties + * All properties from the configuration + */ + void addConfigurationProperties(Properties properties); + + /** + * This method should add a Javadoc comment to the specified field. The + * field is related to the specified table and is used to hold the value of + * the specified column. + *

+ * + * Important: This method should add a the nonstandard JavaDoc tag + * "@mbggenerated" to the comment. Without this tag, the Eclipse based Java + * merge feature will fail. + * + * @param field + * @param introspectedTable + * @param introspectedColumn + */ + public void addFieldComment(Field field, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn); + + public void addFieldComment(Field field, IntrospectedTable introspectedTable); + + public void addClassComment(InnerClass innerClass, + IntrospectedTable introspectedTable); + + public void addClassComment(InnerClass innerClass, + IntrospectedTable introspectedTable, boolean markAsDoNotDelete); + + public void addEnumComment(InnerEnum innerEnum, + IntrospectedTable introspectedTable); + + public void addGetterComment(Method method, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn); + + public void addSetterComment(Method method, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn); + + public void addGeneralMethodComment(Method method, + IntrospectedTable introspectedTable); + + /** + * This method is called to add a file level comment to a generated java + * file. This method could be used to add a general file comment (such as a + * copyright notice). However, note that the Java file merge function in + * Eclipse does not deal with this comment. If you run the generator + * repeatedly, you will only retain the comment from the initial run. + *

+ * + * The default implementation does nothing. + * + * @param compilationUnit + */ + public void addJavaFileComment(CompilationUnit compilationUnit); + + /** + * This method should add a suitable comment as a child element of the + * specified xmlElement to warn users that the element was generated and is + * subject to regeneration. + * + * @param xmlElement + */ + public void addComment(XmlElement xmlElement); + + /** + * This method is called to add a comment as the first child of the root + * element. This method could be used to add a general file comment (such as + * a copyright notice). However, note that the XML file merge function does + * not deal with this comment. If you run the generator repeatedly, you will + * only retain the comment from the initial run. + *

+ * + * The default implementation does nothing. + * + * @param rootElement + */ + public void addRootComment(XmlElement rootElement); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/DAOMethodNameCalculator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/DAOMethodNameCalculator.java new file mode 100644 index 0000000..8805a11 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/DAOMethodNameCalculator.java @@ -0,0 +1,153 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.api; + +/** + * This interface is used to supply names for DAO methods. Users can provide + * different implementations if the supplied implementations aren't sufficient. + * + * @author Jeff Butler + * + */ +public interface DAOMethodNameCalculator { + /** + * Calculates and returns a name for the insert method. + * + * @param introspectedTable + * @return the calculated name + */ + String getInsertMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the insert selective method. + * + * @param introspectedTable + * @return the calculated name + */ + String getInsertSelectiveMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by primary key without BLOBs + * method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByPrimaryKeyWithoutBLOBsMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by primary key with BLOBs + * method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByPrimaryKeyWithBLOBsMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by primary key selective + * method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByPrimaryKeySelectiveMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the select by primary key method. + * + * @param introspectedTable + * @return the calculated name + */ + String getSelectByPrimaryKeyMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the select by example method. + * + * @param introspectedTable + * @return the calculated name + */ + String getSelectByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the select by example with BLOBs + * method. If the table contains BLOBs, then we will generate different + * select by example methods - one including BLOBs, one not including BLOBs. + * + * @param introspectedTable + * @return the calculated name + */ + String getSelectByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the delete by primary key method. + * + * @param introspectedTable + * @return the calculated name + */ + String getDeleteByPrimaryKeyMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the delete by example method. + * + * @param introspectedTable + * @return the calculated name + */ + String getDeleteByExampleMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the count by example method. + * + * @param introspectedTable + * @return the calculated name + */ + String getCountByExampleMethodName(IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by example selective method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByExampleSelectiveMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by example with BLOBs + * method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable); + + /** + * Calculates and returns a name for the update by example without BLOBs + * method. + * + * @param introspectedTable + * @return the calculated name + */ + String getUpdateByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/FullyQualifiedTable.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/FullyQualifiedTable.java new file mode 100644 index 0000000..8c86677 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/FullyQualifiedTable.java @@ -0,0 +1,336 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import static org.mybatis.generator.internal.util.EqualsUtil.areEqual; +import static org.mybatis.generator.internal.util.HashCodeUtil.SEED; +import static org.mybatis.generator.internal.util.HashCodeUtil.hash; +import static org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString; +import static org.mybatis.generator.internal.util.StringUtility.composeFullyQualifiedTableName; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import org.mybatis.generator.config.Context; + +/** + * @author Jeff Butler + */ +public class FullyQualifiedTable { + + private String introspectedCatalog; + + private String introspectedSchema; + + private String introspectedTableName; + + private String runtimeCatalog; + + private String runtimeSchema; + + private String runtimeTableName; + + private String domainObjectName; + + private String domainObjectSubPackage; + + private String alias; + + private boolean ignoreQualifiersAtRuntime; + + private String beginningDelimiter; + + private String endingDelimiter; + + /** + * This object is used to hold information related to the table itself, not + * the columns in the table. + * + * @param introspectedCatalog + * the actual catalog of the table as returned from + * DatabaseMetaData. This value should only be set if the user + * configured a catalog. Otherwise the DatabaseMetaData is + * reporting some database default that we don't want in the + * generated code. + * + * @param introspectedSchema + * the actual schema of the table as returned from + * DatabaseMetaData. This value should only be set if the user + * configured a schema. Otherwise the DatabaseMetaData is + * reporting some database default that we don't want in the + * generated code. + * + * @param introspectedTableName + * the actual table name as returned from DatabaseMetaData + * + * @param domainObjectName + * the configured domain object name for this table. If nothing + * is configured, we'll build the domain object named based on + * the tableName or runtimeTableName. + * + * @param alias + * a configured alias for the table. This alias will be added to + * the table name in the SQL + * + * @param ignoreQualifiersAtRuntime + * if true, then the catalog and schema qualifiers will be + * ignored when composing fully qualified names in the generated + * SQL. This is used, for example, when the user needs to specify + * a specific schema for generating code but does not want the + * schema in the generated SQL + * + * @param runtimeCatalog + * this is used to "rename" the catalog in the generated SQL. + * This is useful, for example, when generating code against one + * catalog that should run with a different catalog. + * + * @param runtimeSchema + * this is used to "rename" the schema in the generated SQL. This + * is useful, for example, when generating code against one + * schema that should run with a different schema. + * + * @param runtimeTableName + * this is used to "rename" the table in the generated SQL. This + * is useful, for example, when generating code to run with an + * Oracle synonym. The user would have to specify the actual + * table name and schema for generation, but would want to use + * the synonym name in the generated SQL + * + * @param delimitIdentifiers + * if true, then the table identifiers will be delimited at + * runtime. The delimiter characters are obtained from the + * Context. + */ + public FullyQualifiedTable(String introspectedCatalog, + String introspectedSchema, String introspectedTableName, + String domainObjectName, String alias, + boolean ignoreQualifiersAtRuntime, String runtimeCatalog, + String runtimeSchema, String runtimeTableName, + boolean delimitIdentifiers, Context context) { + super(); + this.introspectedCatalog = introspectedCatalog; + this.introspectedSchema = introspectedSchema; + this.introspectedTableName = introspectedTableName; + this.ignoreQualifiersAtRuntime = ignoreQualifiersAtRuntime; + this.runtimeCatalog = runtimeCatalog; + this.runtimeSchema = runtimeSchema; + this.runtimeTableName = runtimeTableName; + + if (stringHasValue(domainObjectName)) { + int index = domainObjectName.lastIndexOf('.'); + if (index == -1) { + this.domainObjectName = domainObjectName; + } else { + this.domainObjectName = domainObjectName.substring(index + 1); + this.domainObjectSubPackage = domainObjectName.substring(0, index); + } + } + + if (alias == null) { + this.alias = null; + } else { + this.alias = alias.trim(); + } + + beginningDelimiter = delimitIdentifiers ? context + .getBeginningDelimiter() : ""; //$NON-NLS-1$ + endingDelimiter = delimitIdentifiers ? context.getEndingDelimiter() + : ""; //$NON-NLS-1$ + } + + public String getIntrospectedCatalog() { + return introspectedCatalog; + } + + public String getIntrospectedSchema() { + return introspectedSchema; + } + + public String getIntrospectedTableName() { + return introspectedTableName; + } + + /** + * @return + */ + public String getFullyQualifiedTableNameAtRuntime() { + StringBuilder localCatalog = new StringBuilder(); + if (!ignoreQualifiersAtRuntime) { + if (stringHasValue(runtimeCatalog)) { + localCatalog.append(runtimeCatalog); + } else if (stringHasValue(introspectedCatalog)) { + localCatalog.append(introspectedCatalog); + } + } + if (localCatalog.length() > 0) { + addDelimiters(localCatalog); + } + + StringBuilder localSchema = new StringBuilder(); + if (!ignoreQualifiersAtRuntime) { + if (stringHasValue(runtimeSchema)) { + localSchema.append(runtimeSchema); + } else if (stringHasValue(introspectedSchema)) { + localSchema.append(introspectedSchema); + } + } + if (localSchema.length() > 0) { + addDelimiters(localSchema); + } + + StringBuilder localTableName = new StringBuilder(); + if (stringHasValue(runtimeTableName)) { + localTableName.append(runtimeTableName); + } else { + localTableName.append(introspectedTableName); + } + addDelimiters(localTableName); + + return composeFullyQualifiedTableName(localCatalog + .toString(), localSchema.toString(), localTableName.toString(), + '.'); + } + + /** + * @return + */ + public String getAliasedFullyQualifiedTableNameAtRuntime() { + StringBuilder sb = new StringBuilder(); + + sb.append(getFullyQualifiedTableNameAtRuntime()); + + if (stringHasValue(alias)) { + sb.append(' '); + sb.append(alias); + } + + return sb.toString(); + } + + /** + * This method returns a string that is the fully qualified table name, with + * underscores as the separator. + * + * @return the namespace + */ + public String getIbatis2SqlMapNamespace() { + String localCatalog = stringHasValue(runtimeCatalog) ? runtimeCatalog + : introspectedCatalog; + String localSchema = stringHasValue(runtimeSchema) ? runtimeSchema + : introspectedSchema; + String localTable = stringHasValue(runtimeTableName) ? runtimeTableName + : introspectedTableName; + + return composeFullyQualifiedTableName( + ignoreQualifiersAtRuntime ? null : localCatalog, + ignoreQualifiersAtRuntime ? null : localSchema, + localTable, '_'); + } + + public String getDomainObjectName() { + if (stringHasValue(domainObjectName)) { + return domainObjectName; + } else if (stringHasValue(runtimeTableName)) { + return getCamelCaseString(runtimeTableName, true); + } else { + return getCamelCaseString(introspectedTableName, true); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof FullyQualifiedTable)) { + return false; + } + + FullyQualifiedTable other = (FullyQualifiedTable) obj; + + return areEqual(this.introspectedTableName, + other.introspectedTableName) + && areEqual(this.introspectedCatalog, + other.introspectedCatalog) + && areEqual(this.introspectedSchema, + other.introspectedSchema); + } + + @Override + public int hashCode() { + int result = SEED; + result = hash(result, introspectedTableName); + result = hash(result, introspectedCatalog); + result = hash(result, introspectedSchema); + + return result; + } + + @Override + public String toString() { + return composeFullyQualifiedTableName( + introspectedCatalog, introspectedSchema, introspectedTableName, + '.'); + } + + public String getAlias() { + return alias; + } + + /** + * Calculates a Java package fragment based on the table catalog and schema. + * If qualifiers are ignored, then this method will return an empty string + * + * @return the subpackage for this table + */ + public String getSubPackage(boolean isSubPackagesEnabled) { + StringBuilder sb = new StringBuilder(); + if (!ignoreQualifiersAtRuntime && isSubPackagesEnabled) { + if (stringHasValue(runtimeCatalog)) { + sb.append('.'); + sb.append(runtimeCatalog.toLowerCase()); + } else if (stringHasValue(introspectedCatalog)) { + sb.append('.'); + sb.append(introspectedCatalog.toLowerCase()); + } + + if (stringHasValue(runtimeSchema)) { + sb.append('.'); + sb.append(runtimeSchema.toLowerCase()); + } else if (stringHasValue(introspectedSchema)) { + sb.append('.'); + sb.append(introspectedSchema.toLowerCase()); + } + } + + if (stringHasValue(domainObjectSubPackage)) { + sb.append('.'); + sb.append(domainObjectSubPackage); + } + + // TODO - strip characters that are not valid in package names + return sb.toString(); + } + + private void addDelimiters(StringBuilder sb) { + if (stringHasValue(beginningDelimiter)) { + sb.insert(0, beginningDelimiter); + } + + if (stringHasValue(endingDelimiter)) { + sb.append(endingDelimiter); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/IntrospectedColumn.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/IntrospectedColumn.java new file mode 100644 index 0000000..0a4c946 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/IntrospectedColumn.java @@ -0,0 +1,304 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.mybatis.generator.api; + +import java.sql.Types; +import java.util.Properties; + +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.config.Context; +import org.mybatis.generator.internal.types.Jdbc4Types; +import org.mybatis.generator.internal.util.StringUtility; + +/** + * This class holds information about an introspected column. The class has + * utility methods useful for generating iBATIS objects. + * + * @author Jeff Butler + */ +public class IntrospectedColumn { + protected String actualColumnName; + + protected int jdbcType; + + protected String jdbcTypeName; + + protected boolean nullable; + + protected int length; + + protected int scale; + + protected boolean identity; + + protected boolean isSequenceColumn; + + protected String javaProperty; + + protected FullyQualifiedJavaType fullyQualifiedJavaType; + + protected String tableAlias; + + protected String typeHandler; + + protected Context context; + + protected boolean isColumnNameDelimited; + + protected IntrospectedTable introspectedTable; + + protected Properties properties; + + // any database comment associated with this column. May be null + protected String remarks; + + protected String defaultValue; + + /** + * Constructs a Column definition. This object holds all the information + * about a column that is required to generate Java objects and SQL maps; + */ + public IntrospectedColumn() { + super(); + properties = new Properties(); + } + + public int getJdbcType() { + return jdbcType; + } + + public void setJdbcType(int jdbcType) { + this.jdbcType = jdbcType; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public boolean isNullable() { + return nullable; + } + + public void setNullable(boolean nullable) { + this.nullable = nullable; + } + + public int getScale() { + return scale; + } + + public void setScale(int scale) { + this.scale = scale; + } + + /* + * This method is primarily used for debugging, so we don't externalize the + * strings + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("Actual Column Name: "); //$NON-NLS-1$ + sb.append(actualColumnName); + sb.append(", JDBC Type: "); //$NON-NLS-1$ + sb.append(jdbcType); + sb.append(", Nullable: "); //$NON-NLS-1$ + sb.append(nullable); + sb.append(", Length: "); //$NON-NLS-1$ + sb.append(length); + sb.append(", Scale: "); //$NON-NLS-1$ + sb.append(scale); + sb.append(", Identity: "); //$NON-NLS-1$ + sb.append(identity); + + return sb.toString(); + } + + public void setActualColumnName(String actualColumnName) { + this.actualColumnName = actualColumnName; + isColumnNameDelimited = StringUtility + .stringContainsSpace(actualColumnName); + } + + /** + * @return Returns the identity. + */ + public boolean isIdentity() { + return identity; + } + + /** + * @param identity + * The identity to set. + */ + public void setIdentity(boolean identity) { + this.identity = identity; + } + + public boolean isBLOBColumn() { + String typeName = getJdbcTypeName(); + + return "BINARY".equals(typeName) || "BLOB".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$ + || "CLOB".equals(typeName) || "LONGVARBINARY".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$ + || "LONGVARCHAR".equals(typeName) || "VARBINARY".equals(typeName); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public boolean isStringColumn() { + return fullyQualifiedJavaType.equals(FullyQualifiedJavaType + .getStringInstance()); + } + + public boolean isJdbcCharacterColumn() { + return jdbcType == Types.CHAR || jdbcType == Types.CLOB + || jdbcType == Types.LONGVARCHAR || jdbcType == Types.VARCHAR + || jdbcType == Jdbc4Types.LONGNVARCHAR || jdbcType == Jdbc4Types.NCHAR + || jdbcType == Jdbc4Types.NCLOB || jdbcType == Jdbc4Types.NVARCHAR; + } + + public String getJavaProperty() { + return getJavaProperty(null); + } + + public String getJavaProperty(String prefix) { + if (prefix == null) { + return javaProperty; + } + + StringBuilder sb = new StringBuilder(); + sb.append(prefix); + sb.append(javaProperty); + + return sb.toString(); + } + + public void setJavaProperty(String javaProperty) { + this.javaProperty = javaProperty; + } + + public boolean isJDBCDateColumn() { + return fullyQualifiedJavaType.equals(FullyQualifiedJavaType + .getDateInstance()) + && "DATE".equalsIgnoreCase(jdbcTypeName); //$NON-NLS-1$ + } + + public boolean isJDBCTimeColumn() { + return fullyQualifiedJavaType.equals(FullyQualifiedJavaType + .getDateInstance()) + && "TIME".equalsIgnoreCase(jdbcTypeName); //$NON-NLS-1$ + } + + public String getTypeHandler() { + return typeHandler; + } + + public void setTypeHandler(String typeHandler) { + this.typeHandler = typeHandler; + } + + public String getActualColumnName() { + return actualColumnName; + } + + public void setColumnNameDelimited(boolean isColumnNameDelimited) { + this.isColumnNameDelimited = isColumnNameDelimited; + } + + public boolean isColumnNameDelimited() { + return isColumnNameDelimited; + } + + public String getJdbcTypeName() { + if (jdbcTypeName == null) { + return "OTHER"; //$NON-NLS-1$ + } + + return jdbcTypeName; + } + + public void setJdbcTypeName(String jdbcTypeName) { + this.jdbcTypeName = jdbcTypeName; + } + + public FullyQualifiedJavaType getFullyQualifiedJavaType() { + return fullyQualifiedJavaType; + } + + public void setFullyQualifiedJavaType( + FullyQualifiedJavaType fullyQualifiedJavaType) { + this.fullyQualifiedJavaType = fullyQualifiedJavaType; + } + + public String getTableAlias() { + return tableAlias; + } + + public void setTableAlias(String tableAlias) { + this.tableAlias = tableAlias; + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public IntrospectedTable getIntrospectedTable() { + return introspectedTable; + } + + public void setIntrospectedTable(IntrospectedTable introspectedTable) { + this.introspectedTable = introspectedTable; + } + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties.putAll(properties); + } + + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public boolean isSequenceColumn() { + return isSequenceColumn; + } + + public void setSequenceColumn(boolean isSequenceColumn) { + this.isSequenceColumn = isSequenceColumn; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaFormatter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaFormatter.java new file mode 100644 index 0000000..36229c8 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaFormatter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.config.Context; + +/** + * Objects implementing this interface are used to convert the internal + * representation of the Java DOM classes into a string suitable for + * saving to the file system. Note that the string generated by this + * class will be saved directly to the file system with no additional modifications. + * + * Only one instance of the class will be created in each context. Configuration can + * be passed into the class through the use of properties in the Context. + * + * @author Jeff Butler + * + */ +public interface JavaFormatter { + void setContext(Context context); + String getFormattedContent(CompilationUnit compilationUnit); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaTypeResolver.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaTypeResolver.java new file mode 100644 index 0000000..b548df1 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/JavaTypeResolver.java @@ -0,0 +1,87 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import java.util.List; +import java.util.Properties; + +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.config.Context; + +/** + * This interface describes methods that are required in any Java type resolver. + * A Java type resolver is used to make a default translation between a JDBC + * type as returned from the database introspection process, and a Java type. + * + * @author Jeff Butler + */ +public interface JavaTypeResolver { + /** + * Adds properties for this instance from any properties configured in the + * JavaTypeResolverConfiguration. + * + * This method will be called before any of the get methods. + * + * @param properties + * All properties from the configuration + */ + void addConfigurationProperties(Properties properties); + + /** + * Sets the instance of the Context object associated with this instance. + * + * This method will be called before any of the get methods. + * + * @param context + * The current Context + */ + void setContext(Context context); + + /** + * The generator will supply a list to this method. The implementation class may + * add strings to the list that will be treated as warning messages and + * displayed to the user. The concept of a warning is that code generation + * can continue, but that the results may not be what is expected. + * + * @param warnings + */ + void setWarnings(List warnings); + + /** + * Calculates and returns the Java type that should be associated with this + * column based on the jdbc type, length, and scale of the column. + * + * @param introspectedColumn + * the column whose Java type needs to be calculated + * @return the calculated type, or null if an unsupported data type. If null + * is returned, we will set the type to Object and issue a + * warning unless the column is ignored or otherwise overridden + */ + FullyQualifiedJavaType calculateJavaType( + IntrospectedColumn introspectedColumn); + + /** + * Calculates and returns the JDBC type name that should be associated with + * this column based on the jdbc type, length, and scale of the column. + * + * @param introspectedColumn + * the column whose Java type needs to be calculated + * @return the calculated type name, or null if an unsupported data type. If + * null is returned, we will set the type to OTHER and issue a + * warning unless the column is ignored or otherwise overridden + */ + String calculateJdbcTypeName(IntrospectedColumn introspectedColumn); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/PluginAdapter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/PluginAdapter.java new file mode 100644 index 0000000..9a48c0c --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/PluginAdapter.java @@ -0,0 +1,454 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import java.util.List; +import java.util.Properties; + +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.Interface; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.api.dom.xml.Document; +import org.mybatis.generator.api.dom.xml.XmlElement; +import org.mybatis.generator.config.Context; + +/** + * This class includes no-operation methods for almost every method in the + * Plugin interface. Clients may extend this class to implement some or all of + * the methods in a plugin. + *

+ * This adapter does not implement the validate method - all plugins + * must perform validation. + * + * @author Jeff Butler + * + */ +public abstract class PluginAdapter implements Plugin { + protected Context context; + protected Properties properties; + + public PluginAdapter() { + properties = new Properties(); + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties.putAll(properties); + } + + public List contextGenerateAdditionalJavaFiles() { + return null; + } + + public List contextGenerateAdditionalJavaFiles( + IntrospectedTable introspectedTable) { + return null; + } + + public List contextGenerateAdditionalXmlFiles() { + return null; + } + + public List contextGenerateAdditionalXmlFiles( + IntrospectedTable introspectedTable) { + return null; + } + + public boolean clientCountByExampleMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientCountByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientDeleteByExampleMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientDeleteByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientInsertMethodGenerated(Method method, Interface interfaze, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientInsertMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientGenerated(Interface interfaze, + TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + Method method, Interface interfaze, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean modelFieldGenerated(Field field, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + return true; + } + + public boolean modelGetterMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + return true; + } + + public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean modelRecordWithBLOBsClassGenerated( + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean modelSetterMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + return true; + } + + public boolean sqlMapResultMapWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapCountByExampleElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapDeleteByExampleElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapDocumentGenerated(Document document, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapExampleWhereClauseElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapInsertElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapResultMapWithBLOBsElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapSelectByExampleWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapSelectByPrimaryKeyElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByExampleSelectiveElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByExampleWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByExampleWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByPrimaryKeySelectiveElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapInsertSelectiveElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientInsertSelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientInsertSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public void initialized(IntrospectedTable introspectedTable) { + } + + public boolean sqlMapBaseColumnListElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapBlobColumnListElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerApplyWhereMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerCountByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerDeleteByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerInsertSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerSelectByExampleWithBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerSelectByExampleWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerUpdateByExampleSelectiveMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerUpdateByExampleWithBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerUpdateByExampleWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean providerUpdateByPrimaryKeySelectiveMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectAllMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + return true; + } + + public boolean clientSelectAllMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + return true; + } + + public boolean sqlMapSelectAllElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + return true; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ProgressCallback.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ProgressCallback.java new file mode 100644 index 0000000..bdc4e99 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ProgressCallback.java @@ -0,0 +1,100 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +/** + * This interface can be implemented to return progress information from the + * file generation process. + * + * During the execution of code generation, there are three main operations: + * database introspection, code generation based on the results of + * introspection, and then merging/saving generated files. Methods + * in this interface accordingly and in this order: + *

    + *
  1. introspectionStarted(int)
  2. + *
  3. (Repeatedly) startTask(String)
  4. + *
  5. generationStarted(int)
  6. + *
  7. (Repeatedly) startTask(String)
  8. + *
  9. saveStarted(int)
  10. + *
  11. (Repeatedly) startTask(String)
  12. + *
  13. done()
  14. + *
+ *

+ * Periodically, the checkCancel() method will be called to see if the + * method should be canceled. + *

+ * For planning purposes, the most common use case will have a ratio of 20% + * introspection tasks, 40% generation tasks, and 40% save tasks. + * + * @author Jeff Butler + */ +public interface ProgressCallback { + /** + * Called to note the start of the introspection phase, and to note the + * maximum number of startTask messages that will be sent for the + * introspection phase. + * + * @param totalTasks + * the maximum number of times startTask will be called for the + * introspection phase. + */ + void introspectionStarted(int totalTasks); + + /** + * Called to note the start of the generation phase, and to note the maximum + * number of startTask messages that will be sent for the generation phase. + * + * @param totalTasks + * the maximum number of times startTask will be called for the + * generation phase. + */ + void generationStarted(int totalTasks); + + /** + * Called to note the start of the file saving phase, and to note the + * maximum number of startTask messages that will be sent for the file + * saving phase phase. + * + * @param totalTasks + * the maximum number of times startTask will be called for the + * file saving phase. + */ + void saveStarted(int totalTasks); + + /** + * Called to denote the beginning of a save task + * + * @param taskName + * a descriptive name of the current work step + */ + void startTask(String taskName); + + /** + * This method is called when all generated files have been saved + */ + void done(); + + /** + * The method is called periodically during a long running method. + * If the the implementation throws InterruptedException then + * the method will be canceled. Any files that have already been saved will + * remain on the file system. + * + * @throws InterruptedException + * if the operation should be halted + */ + void checkCancel() throws InterruptedException; +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ShellRunner.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ShellRunner.java new file mode 100644 index 0000000..fbe9a8d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/ShellRunner.java @@ -0,0 +1,228 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import org.mybatis.generator.config.Configuration; +import org.mybatis.generator.config.xml.ConfigurationParser; +import org.mybatis.generator.exception.InvalidConfigurationException; +import org.mybatis.generator.exception.XMLParserException; +import org.mybatis.generator.internal.DefaultShellCallback; +import org.mybatis.generator.logging.LogFactory; + +/** + * This class allows the code generator to be run from the command line. + * + * @author Jeff Butler + */ +public class ShellRunner { + private static final String CONFIG_FILE = "-configfile"; //$NON-NLS-1$ + private static final String OVERWRITE = "-overwrite"; //$NON-NLS-1$ + private static final String CONTEXT_IDS = "-contextids"; //$NON-NLS-1$ + private static final String TABLES = "-tables"; //$NON-NLS-1$ + private static final String VERBOSE = "-verbose"; //$NON-NLS-1$ + private static final String FORCE_JAVA_LOGGING = "-forceJavaLogging"; //$NON-NLS-1$ + private static final String HELP_1 = "-?"; //$NON-NLS-1$ + private static final String HELP_2 = "-h"; //$NON-NLS-1$ + + public static void main(String[] args) { + if (args.length == 0) { + usage(); + System.exit(0); + return; // only to satisfy compiler, never returns + } + + Map arguments = parseCommandLine(args); + + if (arguments.containsKey(HELP_1)) { + usage(); + System.exit(0); + return; // only to satisfy compiler, never returns + } + + if (!arguments.containsKey(CONFIG_FILE)) { + writeLine(getString("RuntimeError.0")); //$NON-NLS-1$ + return; + } + + List warnings = new ArrayList(); + + String configfile = arguments.get(CONFIG_FILE); + File configurationFile = new File(configfile); + if (!configurationFile.exists()) { + writeLine(getString("RuntimeError.1", configfile)); //$NON-NLS-1$ + return; + } + + Set fullyqualifiedTables = new HashSet(); + if (arguments.containsKey(TABLES)) { + StringTokenizer st = new StringTokenizer(arguments.get(TABLES), ","); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String s = st.nextToken().trim(); + if (s.length() > 0) { + fullyqualifiedTables.add(s); + } + } + } + + Set contexts = new HashSet(); + if (arguments.containsKey(CONTEXT_IDS)) { + StringTokenizer st = new StringTokenizer( + arguments.get(CONTEXT_IDS), ","); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String s = st.nextToken().trim(); + if (s.length() > 0) { + contexts.add(s); + } + } + } + + try { + ConfigurationParser cp = new ConfigurationParser(warnings); + Configuration config = cp.parseConfiguration(configurationFile); + + DefaultShellCallback shellCallback = new DefaultShellCallback( + arguments.containsKey(OVERWRITE)); + + MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, shellCallback, warnings); + + ProgressCallback progressCallback = arguments.containsKey(VERBOSE) ? new VerboseProgressCallback() + : null; + + myBatisGenerator.generate(progressCallback, contexts, fullyqualifiedTables); + + } catch (XMLParserException e) { + writeLine(getString("Progress.3")); //$NON-NLS-1$ + writeLine(); + for (String error : e.getErrors()) { + writeLine(error); + } + + return; + } catch (SQLException e) { + e.printStackTrace(); + return; + } catch (IOException e) { + e.printStackTrace(); + return; + } catch (InvalidConfigurationException e) { + writeLine(getString("Progress.16")); //$NON-NLS-1$ + for (String error : e.getErrors()) { + writeLine(error); + } + return; + } catch (InterruptedException e) { + // ignore (will never happen with the DefaultShellCallback) + ; + } + + for (String warning : warnings) { + writeLine(warning); + } + + if (warnings.size() == 0) { + writeLine(getString("Progress.4")); //$NON-NLS-1$ + } else { + writeLine(); + writeLine(getString("Progress.5")); //$NON-NLS-1$ + } + } + + private static void usage() { + String lines = getString("Usage.Lines"); //$NON-NLS-1$ + int iLines = Integer.parseInt(lines); + for (int i = 0; i < iLines; i++) { + String key = "Usage." + i; //$NON-NLS-1$ + writeLine(getString(key)); + } + } + + private static void writeLine(String message) { + System.out.println(message); + } + + private static void writeLine() { + System.out.println(); + } + + private static Map parseCommandLine(String[] args) { + List errors = new ArrayList(); + Map arguments = new HashMap(); + + for (int i = 0; i < args.length; i++) { + if (CONFIG_FILE.equalsIgnoreCase(args[i])) { + if ((i + 1) < args.length) { + arguments.put(CONFIG_FILE, args[i + 1]); + } else { + errors.add(getString( + "RuntimeError.19", CONFIG_FILE)); //$NON-NLS-1$ + } + i++; + } else if (OVERWRITE.equalsIgnoreCase(args[i])) { + arguments.put(OVERWRITE, "Y"); //$NON-NLS-1$ + } else if (VERBOSE.equalsIgnoreCase(args[i])) { + arguments.put(VERBOSE, "Y"); //$NON-NLS-1$ + } else if (HELP_1.equalsIgnoreCase(args[i])) { + arguments.put(HELP_1, "Y"); //$NON-NLS-1$ + } else if (HELP_2.equalsIgnoreCase(args[i])) { + // put HELP_1 in the map here too - so we only + // have to check for one entry in the mainline + arguments.put(HELP_1, "Y"); //$NON-NLS-1$ + } else if (FORCE_JAVA_LOGGING.equalsIgnoreCase(args[i])) { + LogFactory.forceJavaLogging(); + } else if (CONTEXT_IDS.equalsIgnoreCase(args[i])) { + if ((i + 1) < args.length) { + arguments.put(CONTEXT_IDS, args[i + 1]); + } else { + errors.add(getString( + "RuntimeError.19", CONTEXT_IDS)); //$NON-NLS-1$ + } + i++; + } else if (TABLES.equalsIgnoreCase(args[i])) { + if ((i + 1) < args.length) { + arguments.put(TABLES, args[i + 1]); + } else { + errors.add(getString("RuntimeError.19", TABLES)); //$NON-NLS-1$ + } + i++; + } else { + errors.add(getString("RuntimeError.20", args[i])); //$NON-NLS-1$ + } + } + + if (!errors.isEmpty()) { + for (String error : errors) { + writeLine(error); + } + + System.exit(-1); + } + + return arguments; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/VerboseProgressCallback.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/VerboseProgressCallback.java new file mode 100644 index 0000000..8125a39 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/VerboseProgressCallback.java @@ -0,0 +1,38 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.api; + +import org.mybatis.generator.internal.NullProgressCallback; + +/** + * @author Jeff Butler + * + */ +public class VerboseProgressCallback extends NullProgressCallback { + + /** + * + */ + public VerboseProgressCallback() { + super(); + } + + @Override + public void startTask(String taskName) { + System.out.println(taskName); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/XmlFormatter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/XmlFormatter.java new file mode 100644 index 0000000..631406c --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/XmlFormatter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api; + +import org.mybatis.generator.api.dom.xml.Document; +import org.mybatis.generator.config.Context; + +/** + * Objects implementing this interface are used to convert the internal + * representation of the XML DOM classes into a string suitable for + * saving to the file system. Note that the string generated by this + * class will be saved directly to the file system with no additional modifications. + * + * Only one instance of the class will be created in each context. Configuration can + * be passed into the class through the use of properties in the Context. + * + * @author Jeff Butler + * + */ +public interface XmlFormatter { + void setContext(Context context); + String getFormattedContent(Document document); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultJavaFormatter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultJavaFormatter.java new file mode 100644 index 0000000..927c9b7 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultJavaFormatter.java @@ -0,0 +1,39 @@ +/* + * Copyright 2011 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom; + +import org.mybatis.generator.api.JavaFormatter; +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.config.Context; + +/** + * This class is the default formatter for generated Java. This class will use the + * built in formatting of the DOM classes directly. + * + * @author Jeff Butler + * + */ +public class DefaultJavaFormatter implements JavaFormatter { + protected Context context; + + public String getFormattedContent(CompilationUnit compilationUnit) { + return compilationUnit.getFormattedContent(); + } + + public void setContext(Context context) { + this.context = context; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultXmlFormatter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultXmlFormatter.java new file mode 100644 index 0000000..701869d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/DefaultXmlFormatter.java @@ -0,0 +1,39 @@ +/* + * Copyright 2011 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom; + +import org.mybatis.generator.api.XmlFormatter; +import org.mybatis.generator.api.dom.xml.Document; +import org.mybatis.generator.config.Context; + +/** + * This class is the default formatter for generated XML. This class will use the + * built in formatting of the DOM classes directly. + * + * @author Jeff Butler + * + */ +public class DefaultXmlFormatter implements XmlFormatter { + protected Context context; + + public String getFormattedContent(Document document) { + return document.getFormattedContent(); + } + + public void setContext(Context context) { + this.context = context; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/OutputUtilities.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/OutputUtilities.java new file mode 100644 index 0000000..4afd157 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/OutputUtilities.java @@ -0,0 +1,106 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom; + +import java.util.Set; +import java.util.TreeSet; + +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; + +/** + * @author Jeff Butler + */ +public class OutputUtilities { + private static final String lineSeparator; + + static { + String ls = System.getProperty("line.separator"); //$NON-NLS-1$ + if (ls == null) { + ls = "\n"; //$NON-NLS-1$ + } + lineSeparator = ls; + } + + /** + * Utility class - no instances allowed + */ + private OutputUtilities() { + super(); + } + + /** + * Utility method that indents the buffer by the default amount for Java + * (four spaces per indent level). + * + * @param sb + * a StringBuilder to append to + * @param indentLevel + * the required indent level + */ + public static void javaIndent(StringBuilder sb, int indentLevel) { + for (int i = 0; i < indentLevel; i++) { + sb.append(" "); //$NON-NLS-1$ + } + } + + /** + * Utility method that indents the buffer by the default amount for XML (two + * spaces per indent level). + * + * @param sb + * a StringBuilder to append to + * @param indentLevel + * the required indent level + */ + public static void xmlIndent(StringBuilder sb, int indentLevel) { + for (int i = 0; i < indentLevel; i++) { + sb.append(" "); //$NON-NLS-1$ + } + } + + /** + * Utility method. Adds a newline character to a StringBuilder. + * + * @param sb + * the StringBuilder to be appended to + */ + public static void newLine(StringBuilder sb) { + sb.append(lineSeparator); + } + + /** + * returns a unique set of "import xxx;" Strings for the set of types + * + * @param importedTypes + * @return + */ + public static Set calculateImports( + Set importedTypes) { + StringBuilder sb = new StringBuilder(); + Set importStrings = new TreeSet(); + for (FullyQualifiedJavaType fqjt : importedTypes) { + for (String importString : fqjt.getImportList()) { + sb.setLength(0); + sb.append("import "); //$NON-NLS-1$ + sb.append(importString); + sb.append(';'); + importStrings.add(sb.toString()); + } + } + + return importStrings; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/CompilationUnit.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/CompilationUnit.java new file mode 100644 index 0000000..e43c62e --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/CompilationUnit.java @@ -0,0 +1,63 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.List; +import java.util.Set; + +/** + * This interface describes methods common to all Java compilation units (Java + * classes, interfaces, and enums). + * + * @author Jeff Butler + */ +public interface CompilationUnit { + String getFormattedContent(); + + Set getImportedTypes(); + + Set getStaticImports(); + + FullyQualifiedJavaType getSuperClass(); + + boolean isJavaInterface(); + + boolean isJavaEnumeration(); + + Set getSuperInterfaceTypes(); + + FullyQualifiedJavaType getType(); + + void addImportedType(FullyQualifiedJavaType importedType); + + void addImportedTypes(Set importedTypes); + + void addStaticImport(String staticImport); + + void addStaticImports(Set staticImports); + + /** + * Comments will be written at the top of the file as is, we do not append + * any start or end comment characters. + * + * Note that in the Eclipse plugin, file comments will not be merged. + * + * @param commentLine + */ + void addFileCommentLine(String commentLine); + + List getFileCommentLines(); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Field.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Field.java new file mode 100644 index 0000000..589bf9b --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Field.java @@ -0,0 +1,151 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public class Field extends JavaElement { + private FullyQualifiedJavaType type; + private String name; + private String initializationString; + private boolean isTransient; + private boolean isVolatile; + + /** + * + */ + public Field() { + // use a default name to avoid NPE + this("foo", FullyQualifiedJavaType.getIntInstance()); //$NON-NLS-1$ + } + + public Field(String name, FullyQualifiedJavaType type) { + super(); + this.name = name; + this.type = type; + } + + public Field(Field field) { + super(field); + this.type = field.type; + this.name = field.name; + this.initializationString = field.initializationString; + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + /** + * @param name + * The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return Returns the type. + */ + public FullyQualifiedJavaType getType() { + return type; + } + + /** + * @param type + * The type to set. + */ + public void setType(FullyQualifiedJavaType type) { + this.type = type; + } + + /** + * @return Returns the initializationString. + */ + public String getInitializationString() { + return initializationString; + } + + /** + * @param initializationString + * The initializationString to set. + */ + public void setInitializationString(String initializationString) { + this.initializationString = initializationString; + } + + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + + addFormattedJavadoc(sb, indentLevel); + addFormattedAnnotations(sb, indentLevel); + + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(getVisibility().getValue()); + + if (isStatic()) { + sb.append("static "); //$NON-NLS-1$ + } + + if (isFinal()) { + sb.append("final "); //$NON-NLS-1$ + } + + if (isTransient()) { + sb.append("transient "); //$NON-NLS-1$ + } + + if (isVolatile()) { + sb.append("volatile "); //$NON-NLS-1$ + } + + sb.append(type.getShortName()); + + sb.append(' '); + sb.append(name); + + if (initializationString != null && initializationString.length() > 0) { + sb.append(" = "); //$NON-NLS-1$ + sb.append(initializationString); + } + + sb.append(';'); + + return sb.toString(); + } + + public boolean isTransient() { + return isTransient; + } + + public void setTransient(boolean isTransient) { + this.isTransient = isTransient; + } + + public boolean isVolatile() { + return isVolatile; + } + + public void setVolatile(boolean isVolatile) { + this.isVolatile = isVolatile; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/FullyQualifiedJavaType.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/FullyQualifiedJavaType.java new file mode 100644 index 0000000..0e347d6 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/FullyQualifiedJavaType.java @@ -0,0 +1,484 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * @author Jeff Butler + */ +public class FullyQualifiedJavaType implements + Comparable { + private static final String JAVA_LANG = "java.lang"; //$NON-NLS-1$ + private static FullyQualifiedJavaType intInstance = null; + private static FullyQualifiedJavaType stringInstance = null; + private static FullyQualifiedJavaType booleanPrimitiveInstance = null; + private static FullyQualifiedJavaType objectInstance = null; + private static FullyQualifiedJavaType dateInstance = null; + private static FullyQualifiedJavaType criteriaInstance = null; + private static FullyQualifiedJavaType generatedCriteriaInstance = null; + + /** + * The short name without any generic arguments + */ + private String baseShortName; + + /** + * The fully qualified name without any generic arguments + */ + private String baseQualifiedName; + + private boolean explicitlyImported; + private String packageName; + private boolean primitive; + private PrimitiveTypeWrapper primitiveTypeWrapper; + private List typeArguments; + + // the following three values are used for dealing with wildcard types + private boolean wildcardType; + private boolean boundedWildcard; + private boolean extendsBoundedWildcard; + + /** + * Use this constructor to construct a generic type with the specified type + * parameters + * + * @param fullTypeSpecification + */ + public FullyQualifiedJavaType(String fullTypeSpecification) { + super(); + typeArguments = new ArrayList(); + parse(fullTypeSpecification); + } + + /** + * @return Returns the explicitlyImported. + */ + public boolean isExplicitlyImported() { + return explicitlyImported; + } + + /** + * This method returns the fully qualified name - including any generic type + * parameters + * + * @return Returns the fullyQualifiedName. + */ + public String getFullyQualifiedName() { + StringBuilder sb = new StringBuilder(); + if (wildcardType) { + sb.append('?'); + if (boundedWildcard) { + if (extendsBoundedWildcard) { + sb.append(" extends "); //$NON-NLS-1$ + } else { + sb.append(" super "); //$NON-NLS-1$ + } + + sb.append(baseQualifiedName); + } + } else { + sb.append(baseQualifiedName); + } + + if (typeArguments.size() > 0) { + boolean first = true; + sb.append('<'); + for (FullyQualifiedJavaType fqjt : typeArguments) { + if (first) { + first = false; + } else { + sb.append(", "); //$NON-NLS-1$ + } + sb.append(fqjt.getFullyQualifiedName()); + + } + sb.append('>'); + } + + return sb.toString(); + } + + /** + * Returns a list of Strings that are the fully qualified names of this + * type, and any generic type argument associated with this type. + */ + public List getImportList() { + List answer = new ArrayList(); + if (isExplicitlyImported()) { + int index = baseShortName.indexOf('.'); + if (index == -1) { + answer.add(baseQualifiedName); + } else { + // an inner class is specified, only import the top + // level class + StringBuilder sb = new StringBuilder(); + sb.append(packageName); + sb.append('.'); + sb.append(baseShortName.substring(0, index)); + answer.add(sb.toString()); + } + } + + for (FullyQualifiedJavaType fqjt : typeArguments) { + answer.addAll(fqjt.getImportList()); + } + + return answer; + } + + /** + * @return Returns the packageName. + */ + public String getPackageName() { + return packageName; + } + + /** + * @return Returns the shortName - including any type arguments. + */ + public String getShortName() { + StringBuilder sb = new StringBuilder(); + if (wildcardType) { + sb.append('?'); + if (boundedWildcard) { + if (extendsBoundedWildcard) { + sb.append(" extends "); //$NON-NLS-1$ + } else { + sb.append(" super "); //$NON-NLS-1$ + } + + sb.append(baseShortName); + } + } else { + sb.append(baseShortName); + } + + if (typeArguments.size() > 0) { + boolean first = true; + sb.append('<'); + for (FullyQualifiedJavaType fqjt : typeArguments) { + if (first) { + first = false; + } else { + sb.append(", "); //$NON-NLS-1$ + } + sb.append(fqjt.getShortName()); + + } + sb.append('>'); + } + + return sb.toString(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof FullyQualifiedJavaType)) { + return false; + } + + FullyQualifiedJavaType other = (FullyQualifiedJavaType) obj; + + return getFullyQualifiedName().equals(other.getFullyQualifiedName()); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return getFullyQualifiedName().hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getFullyQualifiedName(); + } + + /** + * @return Returns the primitive. + */ + public boolean isPrimitive() { + return primitive; + } + + /** + * @return Returns the wrapperClass. + */ + public PrimitiveTypeWrapper getPrimitiveTypeWrapper() { + return primitiveTypeWrapper; + } + + public static final FullyQualifiedJavaType getIntInstance() { + if (intInstance == null) { + intInstance = new FullyQualifiedJavaType("int"); //$NON-NLS-1$ + } + + return intInstance; + } + + public static final FullyQualifiedJavaType getNewMapInstance() { + // always return a new instance because the type may be parameterized + return new FullyQualifiedJavaType("java.util.Map"); //$NON-NLS-1$ + } + + public static final FullyQualifiedJavaType getNewListInstance() { + // always return a new instance because the type may be parameterized + return new FullyQualifiedJavaType("java.util.List"); //$NON-NLS-1$ + } + + public static final FullyQualifiedJavaType getNewHashMapInstance() { + // always return a new instance because the type may be parameterized + return new FullyQualifiedJavaType("java.util.HashMap"); //$NON-NLS-1$ + } + + public static final FullyQualifiedJavaType getNewArrayListInstance() { + // always return a new instance because the type may be parameterized + return new FullyQualifiedJavaType("java.util.ArrayList"); //$NON-NLS-1$ + } + + public static final FullyQualifiedJavaType getNewIteratorInstance() { + // always return a new instance because the type may be parameterized + return new FullyQualifiedJavaType("java.util.Iterator"); //$NON-NLS-1$ + } + + public static final FullyQualifiedJavaType getStringInstance() { + if (stringInstance == null) { + stringInstance = new FullyQualifiedJavaType("java.lang.String"); //$NON-NLS-1$ + } + + return stringInstance; + } + + public static final FullyQualifiedJavaType getBooleanPrimitiveInstance() { + if (booleanPrimitiveInstance == null) { + booleanPrimitiveInstance = new FullyQualifiedJavaType("boolean"); //$NON-NLS-1$ + } + + return booleanPrimitiveInstance; + } + + public static final FullyQualifiedJavaType getObjectInstance() { + if (objectInstance == null) { + objectInstance = new FullyQualifiedJavaType("java.lang.Object"); //$NON-NLS-1$ + } + + return objectInstance; + } + + public static final FullyQualifiedJavaType getDateInstance() { + if (dateInstance == null) { + dateInstance = new FullyQualifiedJavaType("java.util.Date"); //$NON-NLS-1$ + } + + return dateInstance; + } + + public static final FullyQualifiedJavaType getCriteriaInstance() { + if (criteriaInstance == null) { + criteriaInstance = new FullyQualifiedJavaType("Criteria"); //$NON-NLS-1$ + } + + return criteriaInstance; + } + + public static final FullyQualifiedJavaType getGeneratedCriteriaInstance() { + if (generatedCriteriaInstance == null) { + generatedCriteriaInstance = new FullyQualifiedJavaType( + "GeneratedCriteria"); //$NON-NLS-1$ + } + + return generatedCriteriaInstance; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(FullyQualifiedJavaType other) { + return getFullyQualifiedName().compareTo(other.getFullyQualifiedName()); + } + + public void addTypeArgument(FullyQualifiedJavaType type) { + typeArguments.add(type); + } + + private void parse(String fullTypeSpecification) { + String spec = fullTypeSpecification.trim(); + + if (spec.startsWith("?")) { //$NON-NLS-1$ + wildcardType = true; + spec = spec.substring(1).trim(); + if (spec.startsWith("extends ")) { //$NON-NLS-1$ + boundedWildcard = true; + extendsBoundedWildcard = true; + spec = spec.substring(8); + } else if (spec.startsWith("super ")) { //$NON-NLS-1$ + boundedWildcard = true; + extendsBoundedWildcard = false; + spec = spec.substring(6); + } else { + boundedWildcard = false; + } + parse(spec); + } else { + int index = fullTypeSpecification.indexOf('<'); + if (index == -1) { + simpleParse(fullTypeSpecification); + } else { + simpleParse(fullTypeSpecification.substring(0, index)); + genericParse(fullTypeSpecification.substring(index)); + } + } + } + + private void simpleParse(String typeSpecification) { + baseQualifiedName = typeSpecification.trim(); + if (baseQualifiedName.contains(".")) { //$NON-NLS-1$ + packageName = getPackage(baseQualifiedName); + baseShortName = baseQualifiedName + .substring(packageName.length() + 1); + int index = baseShortName.lastIndexOf('.'); + if (index != -1) { + baseShortName = baseShortName.substring(index + 1); + } + + if (JAVA_LANG.equals(packageName)) { //$NON-NLS-1$ + explicitlyImported = false; + } else { + explicitlyImported = true; + } + } else { + baseShortName = baseQualifiedName; + explicitlyImported = false; + packageName = ""; //$NON-NLS-1$ + + if ("byte".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper.getByteInstance(); + } else if ("short".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper.getShortInstance(); + } else if ("int".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper + .getIntegerInstance(); + } else if ("long".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper.getLongInstance(); + } else if ("char".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper + .getCharacterInstance(); + } else if ("float".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper.getFloatInstance(); + } else if ("double".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper.getDoubleInstance(); + } else if ("boolean".equals(baseQualifiedName)) { //$NON-NLS-1$ + primitive = true; + primitiveTypeWrapper = PrimitiveTypeWrapper + .getBooleanInstance(); + } else { + primitive = false; + primitiveTypeWrapper = null; + } + } + } + + private void genericParse(String genericSpecification) { + int lastIndex = genericSpecification.lastIndexOf('>'); + if (lastIndex == -1) { + throw new RuntimeException(getString( + "RuntimeError.22", genericSpecification)); //$NON-NLS-1$ + } + String argumentString = genericSpecification.substring(1, lastIndex); + // need to find "," outside of a <> bounds + StringTokenizer st = new StringTokenizer(argumentString, ",<>", true); //$NON-NLS-1$ + int openCount = 0; + StringBuilder sb = new StringBuilder(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("<".equals(token)) { //$NON-NLS-1$ + sb.append(token); + openCount++; + } else if (">".equals(token)) { //$NON-NLS-1$ + sb.append(token); + openCount--; + } else if (",".equals(token)) { //$NON-NLS-1$ + if (openCount == 0) { + typeArguments + .add(new FullyQualifiedJavaType(sb.toString())); + sb.setLength(0); + } else { + sb.append(token); + } + } else { + sb.append(token); + } + } + + if (openCount != 0) { + throw new RuntimeException(getString( + "RuntimeError.22", genericSpecification)); //$NON-NLS-1$ + } + + String finalType = sb.toString(); + if (stringHasValue(finalType)) { + typeArguments.add(new FullyQualifiedJavaType(finalType)); + } + } + + /** + * Returns the package name of a fully qualified type. + * + * This method calculates the package as the part of the fully + * qualified name up to, but not including, the last element. Therefore, + * it does not support fully qualified inner classes. + * Not totally fool proof, but correct in most instances. + * + * @param baseQualifiedName + * @return + */ + private static String getPackage(String baseQualifiedName) { + int index = baseQualifiedName.lastIndexOf('.'); + return baseQualifiedName.substring(0, index); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InitializationBlock.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InitializationBlock.java new file mode 100644 index 0000000..0d8dc21 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InitializationBlock.java @@ -0,0 +1,133 @@ +/* + * Copyright 2010 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +import org.mybatis.generator.api.dom.OutputUtilities; + +public class InitializationBlock { + + private boolean isStatic; + private List bodyLines; + private List javaDocLines; + + public InitializationBlock() { + this(false); + } + + public InitializationBlock(boolean isStatic) { + this.isStatic = isStatic; + bodyLines = new ArrayList(); + javaDocLines = new ArrayList(); + } + + public boolean isStatic() { + return isStatic; + } + + public void setStatic(boolean isStatic) { + this.isStatic = isStatic; + } + + public List getBodyLines() { + return bodyLines; + } + + public void addBodyLine(String line) { + bodyLines.add(line); + } + + public void addBodyLine(int index, String line) { + bodyLines.add(index, line); + } + + public void addBodyLines(Collection lines) { + bodyLines.addAll(lines); + } + + public void addBodyLines(int index, Collection lines) { + bodyLines.addAll(index, lines); + } + + public List getJavaDocLines() { + return javaDocLines; + } + + public void addJavaDocLine(String javaDocLine) { + javaDocLines.add(javaDocLine); + } + + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + + for (String javaDocLine : javaDocLines) { + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(javaDocLine); + OutputUtilities.newLine(sb); + } + + OutputUtilities.javaIndent(sb, indentLevel); + + if (isStatic) { + sb.append("static "); //$NON-NLS-1$ + } + + sb.append('{'); + indentLevel++; + + ListIterator listIter = bodyLines.listIterator(); + while (listIter.hasNext()) { + String line = listIter.next(); + if (line.startsWith("}")) { //$NON-NLS-1$ + indentLevel--; + } + + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(line); + + if ((line.endsWith("{") && !line.startsWith("switch")) //$NON-NLS-1$ //$NON-NLS-2$ + || line.endsWith(":")) { //$NON-NLS-1$ + indentLevel++; + } + + if (line.startsWith("break")) { //$NON-NLS-1$ + // if the next line is '}', then don't outdent + if (listIter.hasNext()) { + String nextLine = listIter.next(); + if (nextLine.startsWith("}")) { //$NON-NLS-1$ + indentLevel++; + } + + // set back to the previous element + listIter.previous(); + } + indentLevel--; + } + } + + indentLevel--; + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append('}'); + + return sb.toString(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerClass.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerClass.java new file mode 100644 index 0000000..2acd890 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerClass.java @@ -0,0 +1,282 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * This class encapsulates the idea of an inner class - it has methods that make + * it easy to generate inner classes. + * + * @author Jeff Butler + */ +public class InnerClass extends JavaElement { + private List fields; + + private List innerClasses; + + private List innerEnums; + + private FullyQualifiedJavaType superClass; + + private FullyQualifiedJavaType type; + + private Set superInterfaceTypes; + + private List methods; + + private boolean isAbstract; + + private List initializationBlocks; + + /** + * + */ + public InnerClass(FullyQualifiedJavaType type) { + super(); + this.type = type; + fields = new ArrayList(); + innerClasses = new ArrayList(); + innerEnums = new ArrayList(); + superInterfaceTypes = new HashSet(); + methods = new ArrayList(); + initializationBlocks = new ArrayList(); + } + + public InnerClass(String typeName) { + this(new FullyQualifiedJavaType(typeName)); + } + + /** + * @return Returns the fields. + */ + public List getFields() { + return fields; + } + + public void addField(Field field) { + fields.add(field); + } + + /** + * @return Returns the superClass. + */ + public FullyQualifiedJavaType getSuperClass() { + return superClass; + } + + /** + * @param superClass + * The superClass to set. + */ + public void setSuperClass(FullyQualifiedJavaType superClass) { + this.superClass = superClass; + } + + public void setSuperClass(String superClassType) { + this.superClass = new FullyQualifiedJavaType(superClassType); + } + + /** + * @return Returns the innerClasses. + */ + public List getInnerClasses() { + return innerClasses; + } + + public void addInnerClass(InnerClass innerClass) { + innerClasses.add(innerClass); + } + + public List getInnerEnums() { + return innerEnums; + } + + public void addInnerEnum(InnerEnum innerEnum) { + innerEnums.add(innerEnum); + } + + public List getInitializationBlocks() { + return initializationBlocks; + } + + public void addInitializationBlock(InitializationBlock initializationBlock) { + initializationBlocks.add(initializationBlock); + } + + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + + addFormattedJavadoc(sb, indentLevel); + addFormattedAnnotations(sb, indentLevel); + + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(getVisibility().getValue()); + + if (isAbstract()) { + sb.append("abstract "); //$NON-NLS-1$ + } + + if (isStatic()) { + sb.append("static "); //$NON-NLS-1$ + } + + if (isFinal()) { + sb.append("final "); //$NON-NLS-1$ + } + + sb.append("class "); //$NON-NLS-1$ + sb.append(getType().getShortName()); + + if (superClass != null) { + sb.append(" extends "); //$NON-NLS-1$ + sb.append(superClass.getShortName()); + } + + if (superInterfaceTypes.size() > 0) { + sb.append(" implements "); //$NON-NLS-1$ + + boolean comma = false; + for (FullyQualifiedJavaType fqjt : superInterfaceTypes) { + if (comma) { + sb.append(", "); //$NON-NLS-1$ + } else { + comma = true; + } + + sb.append(fqjt.getShortName()); + } + } + + sb.append(" {"); //$NON-NLS-1$ + indentLevel++; + + Iterator fldIter = fields.iterator(); + while (fldIter.hasNext()) { + OutputUtilities.newLine(sb); + Field field = fldIter.next(); + sb.append(field.getFormattedContent(indentLevel)); + if (fldIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (initializationBlocks.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator blkIter = initializationBlocks.iterator(); + while (blkIter.hasNext()) { + OutputUtilities.newLine(sb); + InitializationBlock initializationBlock = blkIter.next(); + sb.append(initializationBlock.getFormattedContent(indentLevel)); + if (blkIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (methods.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator mtdIter = methods.iterator(); + while (mtdIter.hasNext()) { + OutputUtilities.newLine(sb); + Method method = mtdIter.next(); + sb.append(method.getFormattedContent(indentLevel, false)); + if (mtdIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (innerClasses.size() > 0) { + OutputUtilities.newLine(sb); + } + Iterator icIter = innerClasses.iterator(); + while (icIter.hasNext()) { + OutputUtilities.newLine(sb); + InnerClass innerClass = icIter.next(); + sb.append(innerClass.getFormattedContent(indentLevel)); + if (icIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (innerEnums.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator ieIter = innerEnums.iterator(); + while (ieIter.hasNext()) { + OutputUtilities.newLine(sb); + InnerEnum innerEnum = ieIter.next(); + sb.append(innerEnum.getFormattedContent(indentLevel)); + if (ieIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + indentLevel--; + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append('}'); + + return sb.toString(); + } + + /** + * @return Returns the superInterfaces. + */ + public Set getSuperInterfaceTypes() { + return superInterfaceTypes; + } + + public void addSuperInterface(FullyQualifiedJavaType superInterface) { + superInterfaceTypes.add(superInterface); + } + + /** + * @return Returns the methods. + */ + public List getMethods() { + return methods; + } + + public void addMethod(Method method) { + methods.add(method); + } + + /** + * @return Returns the type. + */ + public FullyQualifiedJavaType getType() { + return type; + } + + public boolean isAbstract() { + return isAbstract; + } + + public void setAbstract(boolean isAbtract) { + this.isAbstract = isAbtract; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerEnum.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerEnum.java new file mode 100644 index 0000000..a0ef401 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/InnerEnum.java @@ -0,0 +1,239 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * This class encapsulates the idea of an inner enum - it has methods that make + * it easy to generate inner enum. + * + * @author Jeff Butler + */ +public class InnerEnum extends JavaElement { + + private List fields; + + private List innerClasses; + + private List innerEnums; + + private FullyQualifiedJavaType type; + + private Set superInterfaceTypes; + + private List methods; + + private List enumConstants; + + /** + * + */ + public InnerEnum(FullyQualifiedJavaType type) { + super(); + this.type = type; + fields = new ArrayList(); + innerClasses = new ArrayList(); + innerEnums = new ArrayList(); + superInterfaceTypes = new HashSet(); + methods = new ArrayList(); + enumConstants = new ArrayList(); + } + + /** + * @return Returns the fields. + */ + public List getFields() { + return fields; + } + + public void addField(Field field) { + fields.add(field); + } + + /** + * @return Returns the innerClasses. + */ + public List getInnerClasses() { + return innerClasses; + } + + public void addInnerClass(InnerClass innerClass) { + innerClasses.add(innerClass); + } + + public List getInnerEnums() { + return innerEnums; + } + + public void addInnerEnum(InnerEnum innerEnum) { + innerEnums.add(innerEnum); + } + + public List getEnumConstants() { + return enumConstants; + } + + public void addEnumConstant(String enumConstant) { + enumConstants.add(enumConstant); + } + + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + + addFormattedJavadoc(sb, indentLevel); + addFormattedAnnotations(sb, indentLevel); + + OutputUtilities.javaIndent(sb, indentLevel); + if (getVisibility() == JavaVisibility.PUBLIC) { + sb.append(getVisibility().getValue()); + } + + sb.append("enum "); //$NON-NLS-1$ + sb.append(getType().getShortName()); + + if (superInterfaceTypes.size() > 0) { + sb.append(" implements "); //$NON-NLS-1$ + + boolean comma = false; + for (FullyQualifiedJavaType fqjt : superInterfaceTypes) { + if (comma) { + sb.append(", "); //$NON-NLS-1$ + } else { + comma = true; + } + + sb.append(fqjt.getShortName()); + } + } + + sb.append(" {"); //$NON-NLS-1$ + indentLevel++; + + Iterator strIter = enumConstants.iterator(); + while (strIter.hasNext()) { + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + String enumConstant = strIter.next(); + sb.append(enumConstant); + + if (strIter.hasNext()) { + sb.append(','); + } else { + sb.append(';'); + } + } + + if (fields.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator fldIter = fields.iterator(); + while (fldIter.hasNext()) { + OutputUtilities.newLine(sb); + Field field = fldIter.next(); + sb.append(field.getFormattedContent(indentLevel)); + if (fldIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (methods.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator mtdIter = methods.iterator(); + while (mtdIter.hasNext()) { + OutputUtilities.newLine(sb); + Method method = mtdIter.next(); + sb.append(method.getFormattedContent(indentLevel, false)); + if (mtdIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (innerClasses.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator icIter = innerClasses.iterator(); + while (icIter.hasNext()) { + OutputUtilities.newLine(sb); + InnerClass innerClass = icIter.next(); + sb.append(innerClass.getFormattedContent(indentLevel)); + if (icIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + if (innerEnums.size() > 0) { + OutputUtilities.newLine(sb); + } + + Iterator ieIter = innerEnums.iterator(); + while (ieIter.hasNext()) { + OutputUtilities.newLine(sb); + InnerEnum innerEnum = ieIter.next(); + sb.append(innerEnum.getFormattedContent(indentLevel)); + if (ieIter.hasNext()) { + OutputUtilities.newLine(sb); + } + } + + indentLevel--; + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append('}'); + + return sb.toString(); + } + + /** + * @return Returns the superInterfaces. + */ + public Set getSuperInterfaceTypes() { + return superInterfaceTypes; + } + + public void addSuperInterface(FullyQualifiedJavaType superInterface) { + superInterfaceTypes.add(superInterface); + } + + /** + * @return Returns the methods. + */ + public List getMethods() { + return methods; + } + + public void addMethod(Method method) { + methods.add(method); + } + + /** + * @return Returns the type. + */ + public FullyQualifiedJavaType getType() { + return type; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Interface.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Interface.java new file mode 100644 index 0000000..f349f24 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Interface.java @@ -0,0 +1,228 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import static org.mybatis.generator.api.dom.OutputUtilities.calculateImports; +import static org.mybatis.generator.api.dom.OutputUtilities.javaIndent; +import static org.mybatis.generator.api.dom.OutputUtilities.newLine; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author Jeff Butler + */ +public class Interface extends JavaElement implements CompilationUnit { + private Set importedTypes; + + private Set staticImports; + + private FullyQualifiedJavaType type; + + private Set superInterfaceTypes; + + private List methods; + + private List fileCommentLines; + + /** + * + */ + public Interface(FullyQualifiedJavaType type) { + super(); + this.type = type; + superInterfaceTypes = new LinkedHashSet(); + methods = new ArrayList(); + importedTypes = new TreeSet(); + fileCommentLines = new ArrayList(); + staticImports = new TreeSet(); + } + + public Interface(String type) { + this(new FullyQualifiedJavaType(type)); + } + + public Set getImportedTypes() { + return Collections.unmodifiableSet(importedTypes); + } + + public void addImportedType(FullyQualifiedJavaType importedType) { + if (importedType.isExplicitlyImported() + && !importedType.getPackageName().equals(type.getPackageName())) { + importedTypes.add(importedType); + } + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + + for (String commentLine : fileCommentLines) { + sb.append(commentLine); + newLine(sb); + } + + if (stringHasValue(getType().getPackageName())) { + sb.append("package "); //$NON-NLS-1$ + sb.append(getType().getPackageName()); + sb.append(';'); + newLine(sb); + newLine(sb); + } + + for (String staticImport : staticImports) { + sb.append("import static "); //$NON-NLS-1$ + sb.append(staticImport); + sb.append(';'); + newLine(sb); + } + + if (staticImports.size() > 0) { + newLine(sb); + } + + Set importStrings = calculateImports(importedTypes); + for (String importString : importStrings) { + sb.append(importString); + newLine(sb); + } + + if (importStrings.size() > 0) { + newLine(sb); + } + + int indentLevel = 0; + + addFormattedJavadoc(sb, indentLevel); + addFormattedAnnotations(sb, indentLevel); + + sb.append(getVisibility().getValue()); + + if (isStatic()) { + sb.append("static "); //$NON-NLS-1$ + } + + if (isFinal()) { + sb.append("final "); //$NON-NLS-1$ + } + + sb.append("interface "); //$NON-NLS-1$ + sb.append(getType().getShortName()); + + if (getSuperInterfaceTypes().size() > 0) { + sb.append(" extends "); //$NON-NLS-1$ + + boolean comma = false; + for (FullyQualifiedJavaType fqjt : getSuperInterfaceTypes()) { + if (comma) { + sb.append(", "); //$NON-NLS-1$ + } else { + comma = true; + } + + sb.append(fqjt.getShortName()); + } + } + + sb.append(" {"); //$NON-NLS-1$ + indentLevel++; + + Iterator mtdIter = getMethods().iterator(); + while (mtdIter.hasNext()) { + newLine(sb); + Method method = mtdIter.next(); + sb.append(method.getFormattedContent(indentLevel, true)); + if (mtdIter.hasNext()) { + newLine(sb); + } + } + + indentLevel--; + newLine(sb); + javaIndent(sb, indentLevel); + sb.append('}'); + + return sb.toString(); + } + + public void addSuperInterface(FullyQualifiedJavaType superInterface) { + superInterfaceTypes.add(superInterface); + } + + /** + * @return Returns the methods. + */ + public List getMethods() { + return methods; + } + + public void addMethod(Method method) { + methods.add(method); + } + + /** + * @return Returns the type. + */ + public FullyQualifiedJavaType getType() { + return type; + } + + public FullyQualifiedJavaType getSuperClass() { + // interfaces do not have superclasses + return null; + } + + public Set getSuperInterfaceTypes() { + return superInterfaceTypes; + } + + public boolean isJavaInterface() { + return true; + } + + public boolean isJavaEnumeration() { + return false; + } + + public void addFileCommentLine(String commentLine) { + fileCommentLines.add(commentLine); + } + + public List getFileCommentLines() { + return fileCommentLines; + } + + public void addImportedTypes(Set importedTypes) { + this.importedTypes.addAll(importedTypes); + } + + public Set getStaticImports() { + return staticImports; + } + + public void addStaticImport(String staticImport) { + staticImports.add(staticImport); + } + + public void addStaticImports(Set staticImports) { + this.staticImports.addAll(staticImports); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaElement.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaElement.java new file mode 100644 index 0000000..9aeb948 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaElement.java @@ -0,0 +1,129 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.List; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public abstract class JavaElement { + private List javaDocLines; + + private JavaVisibility visibility = JavaVisibility.DEFAULT; + + private boolean isStatic; + + private boolean isFinal; + + private List annotations; + + /** + * + */ + public JavaElement() { + super(); + javaDocLines = new ArrayList(); + annotations = new ArrayList(); + } + + /** + * Copy Constructor. + * + * @param original + */ + public JavaElement(JavaElement original) { + this(); + this.annotations.addAll(original.annotations); + this.isFinal = original.isFinal; + this.isStatic = original.isFinal; + this.javaDocLines.addAll(original.javaDocLines); + this.visibility = original.visibility; + } + + /** + * @return Returns the javaDocLines. + */ + public List getJavaDocLines() { + return javaDocLines; + } + + public void addJavaDocLine(String javaDocLine) { + javaDocLines.add(javaDocLine); + } + + public List getAnnotations() { + return annotations; + } + + public void addAnnotation(String annotation) { + annotations.add(annotation); + } + + /** + * @return Returns the visibility. + */ + public JavaVisibility getVisibility() { + return visibility; + } + + /** + * @param visibility + * The visibility to set. + */ + public void setVisibility(JavaVisibility visibility) { + this.visibility = visibility; + } + + public void addSuppressTypeWarningsAnnotation() { + addAnnotation("@SuppressWarnings(\"unchecked\")"); //$NON-NLS-1$ + } + + public void addFormattedJavadoc(StringBuilder sb, int indentLevel) { + for (String javaDocLine : javaDocLines) { + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(javaDocLine); + OutputUtilities.newLine(sb); + } + } + + public void addFormattedAnnotations(StringBuilder sb, int indentLevel) { + for (String annotation : annotations) { + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(annotation); + OutputUtilities.newLine(sb); + } + } + + public boolean isFinal() { + return isFinal; + } + + public void setFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + public boolean isStatic() { + return isStatic; + } + + public void setStatic(boolean isStatic) { + this.isStatic = isStatic; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaVisibility.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaVisibility.java new file mode 100644 index 0000000..2ace3b1 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/JavaVisibility.java @@ -0,0 +1,38 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +/** + * Typesafe enum of possible Java visibility settings + * + * @author Jeff Butler + */ +public enum JavaVisibility { + PUBLIC("public "), //$NON-NLS-1$ + PRIVATE("private "), //$NON-NLS-1$ + PROTECTED("protected "), //$NON-NLS-1$ + DEFAULT(""); //$NON-NLS-1$ + + private String value; + + private JavaVisibility(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Method.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Method.java new file mode 100644 index 0000000..86ae9d2 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Method.java @@ -0,0 +1,305 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public class Method extends JavaElement { + + private List bodyLines; + + private boolean constructor; + + private FullyQualifiedJavaType returnType; + + private String name; + + private List parameters; + + private List exceptions; + + private boolean isSynchronized; + + private boolean isNative; + + /** + * + */ + public Method() { + // use a default name to avoid malformed code + this("bar"); //$NON-NLS-1$ + } + + public Method(String name) { + super(); + bodyLines = new ArrayList(); + parameters = new ArrayList(); + exceptions = new ArrayList(); + this.name = name; + } + + /** + * Copy constructor. Not a truly deep copy, but close enough + * for most purposes. + * + * @param original + */ + public Method(Method original) { + super(original); + bodyLines = new ArrayList(); + parameters = new ArrayList(); + exceptions = new ArrayList(); + this.bodyLines.addAll(original.bodyLines); + this.constructor = original.constructor; + this.exceptions.addAll(original.exceptions); + this.name = original.name; + this.parameters.addAll(original.parameters); + this.returnType = original.returnType; + this.isNative = original.isNative; + this.isSynchronized = original.isSynchronized; + } + + /** + * @return Returns the bodyLines. + */ + public List getBodyLines() { + return bodyLines; + } + + public void addBodyLine(String line) { + bodyLines.add(line); + } + + public void addBodyLine(int index, String line) { + bodyLines.add(index, line); + } + + public void addBodyLines(Collection lines) { + bodyLines.addAll(lines); + } + + public void addBodyLines(int index, Collection lines) { + bodyLines.addAll(index, lines); + } + + public String getFormattedContent(int indentLevel, boolean interfaceMethod) { + StringBuilder sb = new StringBuilder(); + + addFormattedJavadoc(sb, indentLevel); + addFormattedAnnotations(sb, indentLevel); + + OutputUtilities.javaIndent(sb, indentLevel); + + if (!interfaceMethod) { + sb.append(getVisibility().getValue()); + + if (isStatic()) { + sb.append("static "); //$NON-NLS-1$ + } + + if (isFinal()) { + sb.append("final "); //$NON-NLS-1$ + } + + if (isSynchronized()) { + sb.append("synchronized "); //$NON-NLS-1$ + } + + if (isNative()) { + sb.append("native "); //$NON-NLS-1$ + } else if (bodyLines.size() == 0) { + sb.append("abstract "); //$NON-NLS-1$ + } + } + + if (!constructor) { + if (getReturnType() == null) { + sb.append("void"); //$NON-NLS-1$ + } else { + sb.append(getReturnType().getShortName()); + } + sb.append(' '); + } + + sb.append(getName()); + sb.append('('); + + boolean comma = false; + for (Parameter parameter : getParameters()) { + if (comma) { + sb.append(", "); //$NON-NLS-1$ + } else { + comma = true; + } + + sb.append(parameter.getFormattedContent()); + } + + sb.append(')'); + + if (getExceptions().size() > 0) { + sb.append(" throws "); //$NON-NLS-1$ + comma = false; + for (FullyQualifiedJavaType fqjt : getExceptions()) { + if (comma) { + sb.append(", "); //$NON-NLS-1$ + } else { + comma = true; + } + + sb.append(fqjt.getShortName()); + } + } + + // if no body lines, then this is an abstract method + if (bodyLines.size() == 0 || isNative()) { + sb.append(';'); + } else { + sb.append(" {"); //$NON-NLS-1$ + indentLevel++; + + ListIterator listIter = bodyLines.listIterator(); + while (listIter.hasNext()) { + String line = listIter.next(); + if (line.startsWith("}")) { //$NON-NLS-1$ + indentLevel--; + } + + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append(line); + + if ((line.endsWith("{") && !line.startsWith("switch")) //$NON-NLS-1$ //$NON-NLS-2$ + || line.endsWith(":")) { //$NON-NLS-1$ + indentLevel++; + } + + if (line.startsWith("break")) { //$NON-NLS-1$ + // if the next line is '}', then don't outdent + if (listIter.hasNext()) { + String nextLine = listIter.next(); + if (nextLine.startsWith("}")) { //$NON-NLS-1$ + indentLevel++; + } + + // set back to the previous element + listIter.previous(); + } + indentLevel--; + } + } + + indentLevel--; + OutputUtilities.newLine(sb); + OutputUtilities.javaIndent(sb, indentLevel); + sb.append('}'); + } + + return sb.toString(); + } + + /** + * @return Returns the constructor. + */ + public boolean isConstructor() { + return constructor; + } + + /** + * @param constructor + * The constructor to set. + */ + public void setConstructor(boolean constructor) { + this.constructor = constructor; + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + /** + * @param name + * The name to set. + */ + public void setName(String name) { + this.name = name; + } + + public List getParameters() { + return parameters; + } + + public void addParameter(Parameter parameter) { + parameters.add(parameter); + } + + public void addParameter(int index, Parameter parameter) { + parameters.add(index, parameter); + } + + /** + * @return Returns the returnType. + */ + public FullyQualifiedJavaType getReturnType() { + return returnType; + } + + /** + * @param returnType + * The returnType to set. + */ + public void setReturnType(FullyQualifiedJavaType returnType) { + this.returnType = returnType; + } + + /** + * @return Returns the exceptions. + */ + public List getExceptions() { + return exceptions; + } + + public void addException(FullyQualifiedJavaType exception) { + exceptions.add(exception); + } + + public boolean isSynchronized() { + return isSynchronized; + } + + public void setSynchronized(boolean isSynchronized) { + this.isSynchronized = isSynchronized; + } + + public boolean isNative() { + return isNative; + } + + public void setNative(boolean isNative) { + this.isNative = isNative; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Parameter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Parameter.java new file mode 100644 index 0000000..d6d56ab --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/Parameter.java @@ -0,0 +1,101 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jeff Butler + */ +public class Parameter { + private String name; + private FullyQualifiedJavaType type; + private boolean isVarargs; + + private List annotations; + + public Parameter(FullyQualifiedJavaType type, String name, boolean isVarargs) { + super(); + this.name = name; + this.type = type; + this.isVarargs = isVarargs; + annotations = new ArrayList(); + } + + public Parameter(FullyQualifiedJavaType type, String name) { + this(type, name, false); + } + + public Parameter(FullyQualifiedJavaType type, String name, String annotation) { + this(type, name, false); + addAnnotation(annotation); + } + + public Parameter(FullyQualifiedJavaType type, String name, String annotation, boolean isVarargs) { + this(type, name, isVarargs); + addAnnotation(annotation); + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + /** + * @return Returns the type. + */ + public FullyQualifiedJavaType getType() { + return type; + } + + public List getAnnotations() { + return annotations; + } + + public void addAnnotation(String annotation) { + annotations.add(annotation); + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + + for (String annotation : annotations) { + sb.append(annotation); + sb.append(' '); + } + + sb.append(type.getShortName()); + sb.append(' '); + if (isVarargs) { + sb.append("... "); //$NON-NLS-1$ + } + sb.append(name); + + return sb.toString(); + } + + @Override + public String toString() { + return getFormattedContent(); + } + + public boolean isVarargs() { + return isVarargs; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/PrimitiveTypeWrapper.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/PrimitiveTypeWrapper.java new file mode 100644 index 0000000..3e5adff --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/PrimitiveTypeWrapper.java @@ -0,0 +1,125 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.api.dom.java; + +/** + * @author Jeff Butler + * + */ +public class PrimitiveTypeWrapper extends FullyQualifiedJavaType { + private static PrimitiveTypeWrapper booleanInstance; + private static PrimitiveTypeWrapper byteInstance; + private static PrimitiveTypeWrapper characterInstance; + private static PrimitiveTypeWrapper doubleInstance; + private static PrimitiveTypeWrapper floatInstance; + private static PrimitiveTypeWrapper integerInstance; + private static PrimitiveTypeWrapper longInstance; + private static PrimitiveTypeWrapper shortInstance; + + private String toPrimitiveMethod; + + /** + * Use the static getXXXInstance methods to gain access to one of the type + * wrappers. + * + * @param fullyQualifiedName + * fully qualified name of the wrapper type + * @param toPrimitiveMethod + * the method that returns the wrapped primitive + */ + private PrimitiveTypeWrapper(String fullyQualifiedName, + String toPrimitiveMethod) { + super(fullyQualifiedName); + this.toPrimitiveMethod = toPrimitiveMethod; + } + + public String getToPrimitiveMethod() { + return toPrimitiveMethod; + } + + public static PrimitiveTypeWrapper getBooleanInstance() { + if (booleanInstance == null) { + booleanInstance = new PrimitiveTypeWrapper("java.lang.Boolean", //$NON-NLS-1$ + "booleanValue()"); //$NON-NLS-1$ + } + + return booleanInstance; + } + + public static PrimitiveTypeWrapper getByteInstance() { + if (byteInstance == null) { + byteInstance = new PrimitiveTypeWrapper("java.lang.Byte", //$NON-NLS-1$ + "byteValue()"); //$NON-NLS-1$ + } + + return byteInstance; + } + + public static PrimitiveTypeWrapper getCharacterInstance() { + if (characterInstance == null) { + characterInstance = new PrimitiveTypeWrapper("java.lang.Character", //$NON-NLS-1$ + "charValue()"); //$NON-NLS-1$ + } + + return characterInstance; + } + + public static PrimitiveTypeWrapper getDoubleInstance() { + if (doubleInstance == null) { + doubleInstance = new PrimitiveTypeWrapper("java.lang.Double", //$NON-NLS-1$ + "doubleValue()"); //$NON-NLS-1$ + } + + return doubleInstance; + } + + public static PrimitiveTypeWrapper getFloatInstance() { + if (floatInstance == null) { + floatInstance = new PrimitiveTypeWrapper("java.lang.Float", //$NON-NLS-1$ + "floatValue()"); //$NON-NLS-1$ + } + + return floatInstance; + } + + public static PrimitiveTypeWrapper getIntegerInstance() { + if (integerInstance == null) { + integerInstance = new PrimitiveTypeWrapper("java.lang.Integer", //$NON-NLS-1$ + "intValue()"); //$NON-NLS-1$ + } + + return integerInstance; + } + + public static PrimitiveTypeWrapper getLongInstance() { + if (longInstance == null) { + longInstance = new PrimitiveTypeWrapper("java.lang.Long", //$NON-NLS-1$ + "longValue()"); //$NON-NLS-1$ + } + + return longInstance; + } + + public static PrimitiveTypeWrapper getShortInstance() { + if (shortInstance == null) { + shortInstance = new PrimitiveTypeWrapper("java.lang.Short", //$NON-NLS-1$ + "shortValue()"); //$NON-NLS-1$ + } + + return shortInstance; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelClass.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelClass.java new file mode 100644 index 0000000..93d1935 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelClass.java @@ -0,0 +1,145 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.java; + +import static org.mybatis.generator.api.dom.OutputUtilities.calculateImports; +import static org.mybatis.generator.api.dom.OutputUtilities.newLine; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author Jeff Butler + */ +public class TopLevelClass extends InnerClass implements CompilationUnit { + private Set importedTypes; + + private Set staticImports; + + private List fileCommentLines; + + /** + * + */ + public TopLevelClass(FullyQualifiedJavaType type) { + super(type); + importedTypes = new TreeSet(); + fileCommentLines = new ArrayList(); + staticImports = new TreeSet(); + } + + public TopLevelClass(String typeName) { + this(new FullyQualifiedJavaType(typeName)); + } + + /** + * @return Returns the importedTypes. + */ + public Set getImportedTypes() { + return Collections.unmodifiableSet(importedTypes); + } + + public void addImportedType(String importedType) { + addImportedType(new FullyQualifiedJavaType(importedType)); + } + + public void addImportedType(FullyQualifiedJavaType importedType) { + if (importedType != null + && importedType.isExplicitlyImported() + && !importedType.getPackageName().equals( + getType().getPackageName())) { + importedTypes.add(importedType); + } + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + + for (String fileCommentLine : fileCommentLines) { + sb.append(fileCommentLine); + newLine(sb); + } + + if (stringHasValue(getType().getPackageName())) { + sb.append("package "); //$NON-NLS-1$ + sb.append(getType().getPackageName()); + sb.append(';'); + newLine(sb); + newLine(sb); + } + + for (String staticImport : staticImports) { + sb.append("import static "); //$NON-NLS-1$ + sb.append(staticImport); + sb.append(';'); + newLine(sb); + } + + if (staticImports.size() > 0) { + newLine(sb); + } + + Set importStrings = calculateImports(importedTypes); + for (String importString : importStrings) { + sb.append(importString); + newLine(sb); + } + + if (importStrings.size() > 0) { + newLine(sb); + } + + sb.append(super.getFormattedContent(0)); + + return sb.toString(); + } + + public boolean isJavaInterface() { + return false; + } + + public boolean isJavaEnumeration() { + return false; + } + + public void addFileCommentLine(String commentLine) { + fileCommentLines.add(commentLine); + } + + public List getFileCommentLines() { + return fileCommentLines; + } + + public void addImportedTypes(Set importedTypes) { + this.importedTypes.addAll(importedTypes); + } + + public Set getStaticImports() { + return staticImports; + } + + public void addStaticImport(String staticImport) { + staticImports.add(staticImport); + } + + public void addStaticImports(Set staticImports) { + this.staticImports.addAll(staticImports); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelEnumeration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelEnumeration.java new file mode 100644 index 0000000..cb62845 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/java/TopLevelEnumeration.java @@ -0,0 +1,140 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.api.dom.java; + +import static org.mybatis.generator.api.dom.OutputUtilities.calculateImports; +import static org.mybatis.generator.api.dom.OutputUtilities.newLine; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author Jeff Butler + * + */ +public class TopLevelEnumeration extends InnerEnum implements CompilationUnit { + private Set importedTypes; + + private Set staticImports; + + private List fileCommentLines; + + /** + * @param type + */ + public TopLevelEnumeration(FullyQualifiedJavaType type) { + super(type); + importedTypes = new TreeSet(); + fileCommentLines = new ArrayList(); + staticImports = new TreeSet(); + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + + for (String fileCommentLine : fileCommentLines) { + sb.append(fileCommentLine); + newLine(sb); + } + + if (getType().getPackageName() != null + && getType().getPackageName().length() > 0) { + sb.append("package "); //$NON-NLS-1$ + sb.append(getType().getPackageName()); + sb.append(';'); + newLine(sb); + newLine(sb); + } + + for (String staticImport : staticImports) { + sb.append("import static "); //$NON-NLS-1$ + sb.append(staticImport); + sb.append(';'); + newLine(sb); + } + + if (staticImports.size() > 0) { + newLine(sb); + } + + Set importStrings = calculateImports(importedTypes); + for (String importString : importStrings) { + sb.append(importString); + newLine(sb); + } + + if (importStrings.size() > 0) { + newLine(sb); + } + + sb.append(super.getFormattedContent(0)); + + return sb.toString(); + } + + public Set getImportedTypes() { + return Collections.unmodifiableSet(importedTypes); + } + + public FullyQualifiedJavaType getSuperClass() { + throw new UnsupportedOperationException(getString("RuntimeError.11")); //$NON-NLS-1$ + } + + public boolean isJavaInterface() { + return false; + } + + public boolean isJavaEnumeration() { + return true; + } + + public void addImportedType(FullyQualifiedJavaType importedType) { + if (importedType.isExplicitlyImported() + && !importedType.getPackageName().equals( + getType().getPackageName())) { + importedTypes.add(importedType); + } + } + + public void addFileCommentLine(String commentLine) { + fileCommentLines.add(commentLine); + } + + public List getFileCommentLines() { + return fileCommentLines; + } + + public void addImportedTypes(Set importedTypes) { + this.importedTypes.addAll(importedTypes); + } + + public Set getStaticImports() { + return staticImports; + } + + public void addStaticImport(String staticImport) { + staticImports.add(staticImport); + } + + public void addStaticImports(Set staticImports) { + this.staticImports.addAll(staticImports); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Attribute.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Attribute.java new file mode 100644 index 0000000..e19a5fd --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Attribute.java @@ -0,0 +1,57 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.xml; + +/** + * @author Jeff Butler + */ +public class Attribute { + private String name; + private String value; + + /** + * + */ + public Attribute(String name, String value) { + super(); + this.name = name; + this.value = value; + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + /** + * @return Returns the value. + */ + public String getValue() { + return value; + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + sb.append(name); + sb.append("=\""); //$NON-NLS-1$ + sb.append(value); + sb.append('\"'); + + return sb.toString(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Document.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Document.java new file mode 100644 index 0000000..fb8f837 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Document.java @@ -0,0 +1,93 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.xml; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public class Document { + private String publicId; + + private String systemId; + + private XmlElement rootElement; + + /** + * + */ + public Document(String publicId, String systemId) { + super(); + this.publicId = publicId; + this.systemId = systemId; + } + + public Document() { + super(); + } + + /** + * @return Returns the rootElement. + */ + public XmlElement getRootElement() { + return rootElement; + } + + /** + * @param rootElement + * The rootElement to set. + */ + public void setRootElement(XmlElement rootElement) { + this.rootElement = rootElement; + } + + /** + * @return Returns the publicId. + */ + public String getPublicId() { + return publicId; + } + + /** + * @return Returns the systemId. + */ + public String getSystemId() { + return systemId; + } + + public String getFormattedContent() { + StringBuilder sb = new StringBuilder(); + + sb.append(""); //$NON-NLS-1$ + + if (publicId != null && systemId != null) { + OutputUtilities.newLine(sb); + sb.append(""); //$NON-NLS-1$ + } + + OutputUtilities.newLine(sb); + sb.append(rootElement.getFormattedContent(0)); + + return sb.toString(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Element.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Element.java new file mode 100644 index 0000000..45fafdb --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/Element.java @@ -0,0 +1,31 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.xml; + +/** + * @author Jeff Butler + */ +public abstract class Element { + + /** + * + */ + public Element() { + super(); + } + + public abstract String getFormattedContent(int indentLevel); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/TextElement.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/TextElement.java new file mode 100644 index 0000000..228b0df --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/TextElement.java @@ -0,0 +1,45 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.xml; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public class TextElement extends Element { + private String content; + + /** + * + */ + public TextElement(String content) { + super(); + this.content = content; + } + + @Override + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + OutputUtilities.xmlIndent(sb, indentLevel); + sb.append(content); + return sb.toString(); + } + + public String getContent() { + return content; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/XmlElement.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/XmlElement.java new file mode 100644 index 0000000..0bbbaca --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/dom/xml/XmlElement.java @@ -0,0 +1,126 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.api.dom.xml; + +import java.util.ArrayList; +import java.util.List; + +import org.mybatis.generator.api.dom.OutputUtilities; + +/** + * @author Jeff Butler + */ +public class XmlElement extends Element { + private List attributes; + + private List elements; + + private String name; + + /** + * + */ + public XmlElement(String name) { + super(); + attributes = new ArrayList(); + elements = new ArrayList(); + this.name = name; + } + + /** + * Copy constructor. Not a truly deep copy, but close enough + * for most purposes. + * + * @param original + */ + public XmlElement(XmlElement original) { + super(); + attributes = new ArrayList(); + attributes.addAll(original.attributes); + elements = new ArrayList(); + elements.addAll(original.elements); + this.name = original.name; + } + + /** + * @return Returns the attributes. + */ + public List getAttributes() { + return attributes; + } + + public void addAttribute(Attribute attribute) { + attributes.add(attribute); + } + + /** + * @return Returns the elements. + */ + public List getElements() { + return elements; + } + + public void addElement(Element element) { + elements.add(element); + } + + public void addElement(int index, Element element) { + elements.add(index, element); + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + @Override + public String getFormattedContent(int indentLevel) { + StringBuilder sb = new StringBuilder(); + + OutputUtilities.xmlIndent(sb, indentLevel); + sb.append('<'); + sb.append(name); + + for (Attribute att : attributes) { + sb.append(' '); + sb.append(att.getFormattedContent()); + } + + if (elements.size() > 0) { + sb.append(" >"); //$NON-NLS-1$ + for (Element element : elements) { + OutputUtilities.newLine(sb); + sb.append(element.getFormattedContent(indentLevel + 1)); + } + OutputUtilities.newLine(sb); + OutputUtilities.xmlIndent(sb, indentLevel); + sb.append("'); + + } else { + sb.append(" />"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/package.html b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/package.html new file mode 100644 index 0000000..8e13e9f --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/api/package.html @@ -0,0 +1,10 @@ + + +Package Description for Main MyBatis Generator API + Classes + + +

Provides the main classes and interfaces used by clients of + MyBatis Generator.

+ + diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractGenerator.java new file mode 100644 index 0000000..812c9c8 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractGenerator.java @@ -0,0 +1,70 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +import java.util.List; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.ProgressCallback; +import org.mybatis.generator.config.Context; + +/** + * + * @author Jeff Butler + * + */ +public abstract class AbstractGenerator { + protected Context context; + protected IntrospectedTable introspectedTable; + protected List warnings; + protected ProgressCallback progressCallback; + + public AbstractGenerator() { + super(); + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public IntrospectedTable getIntrospectedTable() { + return introspectedTable; + } + + public void setIntrospectedTable(IntrospectedTable introspectedTable) { + this.introspectedTable = introspectedTable; + } + + public List getWarnings() { + return warnings; + } + + public void setWarnings(List warnings) { + this.warnings = warnings; + } + + public ProgressCallback getProgressCallback() { + return progressCallback; + } + + public void setProgressCallback(ProgressCallback progressCallback) { + this.progressCallback = progressCallback; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaClientGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaClientGenerator.java new file mode 100644 index 0000000..b66e8e3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaClientGenerator.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +/** + * This class exists to that Java client generators can specify whether + * an XML generator is required to match the methods in the + * Java client. For example, a Java client built entirely with + * annotations does not need matching XML. + * + * @author Jeff Butler + * + */ +public abstract class AbstractJavaClientGenerator extends AbstractJavaGenerator { + + private boolean requiresXMLGenerator; + + public AbstractJavaClientGenerator(boolean requiresXMLGenerator) { + super(); + this.requiresXMLGenerator = requiresXMLGenerator; + } + + /** + * @return true if matching XML is required + */ + public boolean requiresXMLGenerator() { + return requiresXMLGenerator; + } + + /** + * This method returns an instance of the XML generator associated + * with this client generator. + * + * @return the matched XML generator. May return null if no + * XML is required by this generator + */ + public abstract AbstractXmlGenerator getMatchedXMLGenerator(); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaGenerator.java new file mode 100644 index 0000000..6ccafcc --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractJavaGenerator.java @@ -0,0 +1,156 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +import static org.mybatis.generator.internal.util.JavaBeansUtil.getGetterMethodName; +import static org.mybatis.generator.internal.util.JavaBeansUtil.getSetterMethodName; +import static org.mybatis.generator.internal.util.StringUtility.isTrue; + +import java.util.List; +import java.util.Properties; + +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.config.PropertyRegistry; + +/** + * + * @author Jeff Butler + * + */ +public abstract class AbstractJavaGenerator extends AbstractGenerator { + public abstract List getCompilationUnits(); + + public static Method getGetter(Field field) { + Method method = new Method(); + method.setName(getGetterMethodName(field.getName(), field + .getType())); + method.setReturnType(field.getType()); + method.setVisibility(JavaVisibility.PUBLIC); + StringBuilder sb = new StringBuilder(); + sb.append("return "); //$NON-NLS-1$ + sb.append(field.getName()); + sb.append(';'); + method.addBodyLine(sb.toString()); + return method; + } + + public Method getJavaBeansGetter(IntrospectedColumn introspectedColumn) { + FullyQualifiedJavaType fqjt = introspectedColumn + .getFullyQualifiedJavaType(); + String property = introspectedColumn.getJavaProperty(); + + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setReturnType(fqjt); + method.setName(getGetterMethodName(property, fqjt)); + context.getCommentGenerator().addGetterComment(method, + introspectedTable, introspectedColumn); + + StringBuilder sb = new StringBuilder(); + sb.append("return "); //$NON-NLS-1$ + sb.append(property); + sb.append(';'); + method.addBodyLine(sb.toString()); + + return method; + } + + public Field getJavaBeansField(IntrospectedColumn introspectedColumn) { + FullyQualifiedJavaType fqjt = introspectedColumn + .getFullyQualifiedJavaType(); + String property = introspectedColumn.getJavaProperty(); + + Field field = new Field(); + field.setVisibility(JavaVisibility.PRIVATE); + field.setType(fqjt); + field.setName(property); + context.getCommentGenerator().addFieldComment(field, + introspectedTable, introspectedColumn); + + return field; + } + + public Method getJavaBeansSetter(IntrospectedColumn introspectedColumn) { + FullyQualifiedJavaType fqjt = introspectedColumn + .getFullyQualifiedJavaType(); + String property = introspectedColumn.getJavaProperty(); + + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setName(getSetterMethodName(property)); + method.addParameter(new Parameter(fqjt, property)); + context.getCommentGenerator().addSetterComment(method, + introspectedTable, introspectedColumn); + + StringBuilder sb = new StringBuilder(); + if (isTrimStringsEnabled() && introspectedColumn.isStringColumn()) { + sb.append("this."); //$NON-NLS-1$ + sb.append(property); + sb.append(" = "); //$NON-NLS-1$ + sb.append(property); + sb.append(" == null ? null : "); //$NON-NLS-1$ + sb.append(property); + sb.append(".trim();"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else { + sb.append("this."); //$NON-NLS-1$ + sb.append(property); + sb.append(" = "); //$NON-NLS-1$ + sb.append(property); + sb.append(';'); + method.addBodyLine(sb.toString()); + } + + return method; + } + + public boolean isTrimStringsEnabled() { + Properties properties = context + .getJavaModelGeneratorConfiguration().getProperties(); + boolean rc = isTrue(properties + .getProperty(PropertyRegistry.MODEL_GENERATOR_TRIM_STRINGS)); + return rc; + } + + public String getRootClass() { + String rootClass = introspectedTable + .getTableConfigurationProperty(PropertyRegistry.ANY_ROOT_CLASS); + if (rootClass == null) { + Properties properties = context + .getJavaModelGeneratorConfiguration().getProperties(); + rootClass = properties.getProperty(PropertyRegistry.ANY_ROOT_CLASS); + } + + return rootClass; + } + + protected void addDefaultConstructor(TopLevelClass topLevelClass) { + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setConstructor(true); + method.setName(topLevelClass.getType().getShortName()); + method.addBodyLine("super();"); //$NON-NLS-1$ + context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable); + topLevelClass.addMethod(method); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractXmlGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractXmlGenerator.java new file mode 100644 index 0000000..8957a1e --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/AbstractXmlGenerator.java @@ -0,0 +1,27 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +import org.mybatis.generator.api.dom.xml.Document; + +/** + * + * @author Jeff Butler + * + */ +public abstract class AbstractXmlGenerator extends AbstractGenerator { + public abstract Document getDocument(); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/RootClassInfo.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/RootClassInfo.java new file mode 100644 index 0000000..ff5dc7a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/RootClassInfo.java @@ -0,0 +1,126 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.internal.ObjectFactory; + +/** + * + * @author Jeff Butler + * + */ +public class RootClassInfo { + + private static Map rootClassInfoMap; + + static { + rootClassInfoMap = Collections + .synchronizedMap(new HashMap()); + } + + public static RootClassInfo getInstance(String className, + List warnings) { + RootClassInfo classInfo = rootClassInfoMap.get(className); + if (classInfo == null) { + classInfo = new RootClassInfo(className, warnings); + rootClassInfoMap.put(className, classInfo); + } + + return classInfo; + } + + private PropertyDescriptor[] propertyDescriptors; + private String className; + private List warnings; + + private RootClassInfo(String className, List warnings) { + super(); + this.className = className; + this.warnings = warnings; + + if (className == null) { + return; + } + + try { + Class clazz = ObjectFactory.externalClassForName(className); + BeanInfo bi = Introspector.getBeanInfo(clazz); + propertyDescriptors = bi.getPropertyDescriptors(); + } catch (Exception e) { + propertyDescriptors = null; + warnings.add(getString("Warning.20", className)); //$NON-NLS-1$ + } + } + + public boolean containsProperty(IntrospectedColumn introspectedColumn) { + if (propertyDescriptors == null) { + return false; + } + + boolean found = false; + String propertyName = introspectedColumn.getJavaProperty(); + String propertyType = introspectedColumn.getFullyQualifiedJavaType() + .getFullyQualifiedName(); + + // get method names from class and check against this column definition. + // better yet, have a map of method Names. check against it. + for (int i = 0; i < propertyDescriptors.length; i++) { + PropertyDescriptor propertyDescriptor = propertyDescriptors[i]; + + if (propertyDescriptor.getName().equals(propertyName)) { + // property is in the rootClass... + + // Is it the proper type? + if (!propertyDescriptor.getPropertyType().getName().equals( + propertyType)) { + warnings.add(getString("Warning.21", //$NON-NLS-1$ + propertyName, className, propertyType)); + break; + } + + // Does it have a getter? + if (propertyDescriptor.getReadMethod() == null) { + warnings.add(getString("Warning.22", //$NON-NLS-1$ + propertyName, className)); + break; + } + + // Does it have a setter? + if (propertyDescriptor.getWriteMethod() == null) { + warnings.add(getString("Warning.23", //$NON-NLS-1$ + propertyName, className)); + break; + } + + found = true; + break; + } + } + + return found; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/XmlConstants.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/XmlConstants.java new file mode 100644 index 0000000..8c9a460 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/XmlConstants.java @@ -0,0 +1,53 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen; + +/** + * @author Jeff Butler + */ +public class XmlConstants { + + /** + * Utility Class, no instances + */ + private XmlConstants() { + super(); + } + + public static final String IBATIS2_SQL_MAP_SYSTEM_ID = "http://ibatis.apache.org/dtd/sql-map-2.dtd"; //$NON-NLS-1$ + + public static final String IBATIS2_SQL_MAP_PUBLIC_ID = "-//ibatis.apache.org//DTD SQL Map 2.0//EN"; //$NON-NLS-1$ + + public static final String IBATIS2_SQL_MAP_CONFIG_SYSTEM_ID = "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"; //$NON-NLS-1$ + + public static final String IBATIS2_SQL_MAP_CONFIG_PUBLIC_ID = "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"; //$NON-NLS-1$ + + public static final String MYBATIS3_MAPPER_SYSTEM_ID = "http://mybatis.org/dtd/mybatis-3-mapper.dtd"; //$NON-NLS-1$ + + public static final String MYBATIS3_MAPPER_PUBLIC_ID = "-//mybatis.org//DTD Mapper 3.0//EN"; //$NON-NLS-1$ + + public static final String MYBATIS3_MAPPER_CONFIG_SYSTEM_ID = "http://mybatis.org/dtd/mybatis-3-config.dtd"; //$NON-NLS-1$ + + public static final String MYBATIS3_MAPPER_CONFIG_PUBLIC_ID = "-//mybatis.org//DTD Config 3.0//EN"; //$NON-NLS-1$ + + public static final String IBATOR_CONFIG_SYSTEM_ID = "http://ibatis.apache.org/dtd/ibator-config_1_0.dtd"; //$NON-NLS-1$ + + public static final String IBATOR_CONFIG_PUBLIC_ID = "-//Apache Software Foundation//DTD Apache iBATIS Ibator Configuration 1.0//EN"; //$NON-NLS-1$ + + public static final String MYBATIS_GENERATOR_CONFIG_SYSTEM_ID = "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"; //$NON-NLS-1$ + + public static final String MYBATIS_GENERATOR_CONFIG_PUBLIC_ID = "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"; //$NON-NLS-1$ +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/Ibatis2FormattingUtilities.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/Ibatis2FormattingUtilities.java new file mode 100644 index 0000000..65bb904 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/Ibatis2FormattingUtilities.java @@ -0,0 +1,201 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.codegen.ibatis2; + +import static org.mybatis.generator.internal.util.StringUtility.escapeStringForJava; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import java.util.StringTokenizer; + +import org.mybatis.generator.api.IntrospectedColumn; + +/** + * @author Jeff Butler + * + */ +public class Ibatis2FormattingUtilities { + /** + * Utility class - no instances + */ + private Ibatis2FormattingUtilities() { + super(); + } + + public static String getEscapedColumnName( + IntrospectedColumn introspectedColumn) { + StringBuilder sb = new StringBuilder(); + sb.append(escapeStringForIbatis2(introspectedColumn + .getActualColumnName())); + + if (introspectedColumn.isColumnNameDelimited()) { + sb.insert(0, introspectedColumn.getContext() + .getBeginningDelimiter()); + sb.append(introspectedColumn.getContext().getEndingDelimiter()); + } + + return sb.toString(); + } + + /** + * Calculates the string to use in select phrases in SqlMaps. + * + * @return the aliased escaped column name + */ + public static String getAliasedEscapedColumnName( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(introspectedColumn.getTableAlias()); + sb.append('.'); + sb.append(getEscapedColumnName(introspectedColumn)); + return sb.toString(); + } else { + return getEscapedColumnName(introspectedColumn); + } + } + + public static String getParameterClause( + IntrospectedColumn introspectedColumn) { + return getParameterClause(introspectedColumn, null); + } + + public static String getParameterClause( + IntrospectedColumn introspectedColumn, String prefix) { + StringBuilder sb = new StringBuilder(); + + sb.append('#'); + sb.append(introspectedColumn.getJavaProperty(prefix)); + + if (stringHasValue(introspectedColumn.getTypeHandler())) { + sb.append(",jdbcType="); //$NON-NLS-1$ + sb.append(introspectedColumn.getJdbcTypeName()); + sb.append(",handler="); //$NON-NLS-1$ + sb.append(introspectedColumn.getTypeHandler()); + } else { + sb.append(':'); + sb.append(introspectedColumn.getJdbcTypeName()); + } + + sb.append('#'); + + return sb.toString(); + } + + /** + * The phrase to use in a select list. If there is a table alias, the value + * will be "alias.columnName as alias_columnName" + * + * @return the proper phrase + */ + public static String getSelectListPhrase( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(getAliasedEscapedColumnName(introspectedColumn)); + sb.append(" as "); //$NON-NLS-1$ + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(introspectedColumn.getContext() + .getBeginningDelimiter()); + } + sb.append(introspectedColumn.getTableAlias()); + sb.append('_'); + sb.append(escapeStringForIbatis2(introspectedColumn + .getActualColumnName())); + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(introspectedColumn.getContext().getEndingDelimiter()); + } + return sb.toString(); + } else { + return getEscapedColumnName(introspectedColumn); + } + } + + public static String escapeStringForIbatis2(String s) { + StringTokenizer st = new StringTokenizer(s, "$#", true); //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("$".equals(token)) { //$NON-NLS-1$ + sb.append("$$"); //$NON-NLS-1$ + } else if ("#".equals(token)) { //$NON-NLS-1$ + sb.append("##"); //$NON-NLS-1$ + } else { + sb.append(token); + } + } + + return sb.toString(); + } + + /** + * The aliased column name for a select statement generated by the example + * clauses. This is not appropriate for selects in SqlMaps because the + * column is not escaped for iBATIS. If there is a table alias, the value + * will be alias.columnName. + * + * This method is used in the Example classes and the returned value will be + * in a Java string. So we need to escape double quotes if they are the + * delimiters. + * + * @return the aliased column name + */ + public static String getAliasedActualColumnName( + IntrospectedColumn introspectedColumn) { + StringBuilder sb = new StringBuilder(); + if (stringHasValue(introspectedColumn.getTableAlias())) { + sb.append(introspectedColumn.getTableAlias()); + sb.append('.'); + } + + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(escapeStringForJava(introspectedColumn + .getContext().getBeginningDelimiter())); + } + + sb.append(introspectedColumn.getActualColumnName()); + + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(escapeStringForJava(introspectedColumn + .getContext().getEndingDelimiter())); + } + + return sb.toString(); + } + + /** + * The renamed column name for a select statement. If there is a table + * alias, the value will be alias_columnName. This is appropriate for use in + * a result map. + * + * @return the renamed column name + */ + public static String getRenamedColumnNameForResultMap( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(introspectedColumn.getTableAlias()); + sb.append('_'); + sb.append(introspectedColumn.getActualColumnName()); + return sb.toString(); + } else { + return introspectedColumn.getActualColumnName(); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/IntrospectedTableIbatis2Java5Impl.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/IntrospectedTableIbatis2Java5Impl.java new file mode 100644 index 0000000..fcd1bb0 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/ibatis2/IntrospectedTableIbatis2Java5Impl.java @@ -0,0 +1,29 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen.ibatis2; + +/** + * + * @author Jeff Butler + * + */ +public class IntrospectedTableIbatis2Java5Impl extends + IntrospectedTableIbatis2Java2Impl { + @Override + public boolean isJava5Targeted() { + return true; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/IntrospectedTableMyBatis3SimpleImpl.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/IntrospectedTableMyBatis3SimpleImpl.java new file mode 100644 index 0000000..197ad4e --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/IntrospectedTableMyBatis3SimpleImpl.java @@ -0,0 +1,88 @@ +/* + * Copyright 2012 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.codegen.mybatis3; + +import java.util.List; + +import org.mybatis.generator.api.ProgressCallback; +import org.mybatis.generator.codegen.AbstractJavaClientGenerator; +import org.mybatis.generator.codegen.AbstractJavaGenerator; +import org.mybatis.generator.codegen.mybatis3.javamapper.SimpleAnnotatedClientGenerator; +import org.mybatis.generator.codegen.mybatis3.javamapper.SimpleJavaClientGenerator; +import org.mybatis.generator.codegen.mybatis3.model.SimpleModelGenerator; +import org.mybatis.generator.codegen.mybatis3.xmlmapper.SimpleXMLMapperGenerator; +import org.mybatis.generator.internal.ObjectFactory; + +/** + * + * @author Jeff Butler + * + */ +public class IntrospectedTableMyBatis3SimpleImpl extends IntrospectedTableMyBatis3Impl { + public IntrospectedTableMyBatis3SimpleImpl() { + super(); + } + + @Override + protected void calculateXmlMapperGenerator(AbstractJavaClientGenerator javaClientGenerator, + List warnings, + ProgressCallback progressCallback) { + if (javaClientGenerator == null) { + if (context.getSqlMapGeneratorConfiguration() != null) { + xmlMapperGenerator = new SimpleXMLMapperGenerator(); + } + } else { + xmlMapperGenerator = javaClientGenerator.getMatchedXMLGenerator(); + } + + initializeAbstractGenerator(xmlMapperGenerator, warnings, + progressCallback); + } + + @Override + protected AbstractJavaClientGenerator createJavaClientGenerator() { + if (context.getJavaClientGeneratorConfiguration() == null) { + return null; + } + + String type = context.getJavaClientGeneratorConfiguration() + .getConfigurationType(); + + AbstractJavaClientGenerator javaGenerator; + if ("XMLMAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$ + javaGenerator = new SimpleJavaClientGenerator(); + } else if ("ANNOTATEDMAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$ + javaGenerator = new SimpleAnnotatedClientGenerator(); + } else if ("MAPPER".equalsIgnoreCase(type)) { //$NON-NLS-1$ + javaGenerator = new SimpleJavaClientGenerator(); + } else { + javaGenerator = (AbstractJavaClientGenerator) ObjectFactory + .createInternalObject(type); + } + + return javaGenerator; + } + + @Override + protected void calculateJavaModelGenerators(List warnings, + ProgressCallback progressCallback) { + + AbstractJavaGenerator javaGenerator = new SimpleModelGenerator(); + initializeAbstractGenerator(javaGenerator, warnings, + progressCallback); + javaModelGenerators.add(javaGenerator); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/MyBatis3FormattingUtilities.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/MyBatis3FormattingUtilities.java new file mode 100644 index 0000000..3e2d8da --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/codegen/mybatis3/MyBatis3FormattingUtilities.java @@ -0,0 +1,184 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.codegen.mybatis3; + +import static org.mybatis.generator.internal.util.StringUtility.escapeStringForJava; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import org.mybatis.generator.api.IntrospectedColumn; + +/** + * @author Jeff Butler + * + */ +public class MyBatis3FormattingUtilities { + /** + * Utility class - no instances + */ + private MyBatis3FormattingUtilities() { + super(); + } + + public static String getParameterClause( + IntrospectedColumn introspectedColumn) { + return getParameterClause(introspectedColumn, null); + } + + public static String getParameterClause( + IntrospectedColumn introspectedColumn, String prefix) { + StringBuilder sb = new StringBuilder(); + + sb.append("#{"); //$NON-NLS-1$ + sb.append(introspectedColumn.getJavaProperty(prefix)); + sb.append(",jdbcType="); //$NON-NLS-1$ + sb.append(introspectedColumn.getJdbcTypeName()); + + if (stringHasValue(introspectedColumn.getTypeHandler())) { + sb.append(",typeHandler="); //$NON-NLS-1$ + sb.append(introspectedColumn.getTypeHandler()); + } + + sb.append('}'); + + return sb.toString(); + } + + /** + * The phrase to use in a select list. If there is a table alias, the value + * will be "alias.columnName as alias_columnName" + * + * @return the proper phrase + */ + public static String getSelectListPhrase( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(getAliasedEscapedColumnName(introspectedColumn)); + sb.append(" as "); //$NON-NLS-1$ + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(introspectedColumn.getContext() + .getBeginningDelimiter()); + } + sb.append(introspectedColumn.getTableAlias()); + sb.append('_'); + sb.append(escapeStringForMyBatis3(introspectedColumn + .getActualColumnName())); + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(introspectedColumn.getContext().getEndingDelimiter()); + } + return sb.toString(); + } else { + return getEscapedColumnName(introspectedColumn); + } + } + + public static String getEscapedColumnName( + IntrospectedColumn introspectedColumn) { + StringBuilder sb = new StringBuilder(); + sb.append(escapeStringForMyBatis3(introspectedColumn + .getActualColumnName())); + + if (introspectedColumn.isColumnNameDelimited()) { + sb.insert(0, introspectedColumn.getContext() + .getBeginningDelimiter()); + sb.append(introspectedColumn.getContext().getEndingDelimiter()); + } + + return sb.toString(); + } + + /** + * Calculates the string to use in select phrases in SqlMaps. + * + * @return the aliased escaped column name + */ + public static String getAliasedEscapedColumnName( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(introspectedColumn.getTableAlias()); + sb.append('.'); + sb.append(getEscapedColumnName(introspectedColumn)); + return sb.toString(); + } else { + return getEscapedColumnName(introspectedColumn); + } + } + + /** + * The aliased column name for a select statement generated by the example + * clauses. This is not appropriate for selects in SqlMaps because the + * column is not escaped for MyBatis. If there is a table alias, the value + * will be alias.columnName. + * + * This method is used in the Example classes and the returned value will be + * in a Java string. So we need to escape double quotes if they are the + * delimiters. + * + * @return the aliased column name + */ + public static String getAliasedActualColumnName( + IntrospectedColumn introspectedColumn) { + StringBuilder sb = new StringBuilder(); + if (stringHasValue(introspectedColumn.getTableAlias())) { + sb.append(introspectedColumn.getTableAlias()); + sb.append('.'); + } + + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(escapeStringForJava(introspectedColumn + .getContext().getBeginningDelimiter())); + } + + sb.append(introspectedColumn.getActualColumnName()); + + if (introspectedColumn.isColumnNameDelimited()) { + sb.append(escapeStringForJava(introspectedColumn + .getContext().getEndingDelimiter())); + } + + return sb.toString(); + } + + /** + * The renamed column name for a select statement. If there is a table + * alias, the value will be alias_columnName. This is appropriate for use in + * a result map. + * + * @return the renamed column name + */ + public static String getRenamedColumnNameForResultMap( + IntrospectedColumn introspectedColumn) { + if (stringHasValue(introspectedColumn.getTableAlias())) { + StringBuilder sb = new StringBuilder(); + + sb.append(introspectedColumn.getTableAlias()); + sb.append('_'); + sb.append(introspectedColumn.getActualColumnName()); + return sb.toString(); + } else { + return introspectedColumn.getActualColumnName(); + } + } + + public static String escapeStringForMyBatis3(String s) { + // nothing to do for MyBatis3 so far + return s; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnOverride.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnOverride.java new file mode 100644 index 0000000..ccfbffa --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnOverride.java @@ -0,0 +1,138 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringContainsSpace; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * @author Jeff Butler + */ +public class ColumnOverride extends PropertyHolder { + + private String columnName; + + private String javaProperty; + + private String jdbcType; + + private String javaType; + + private String typeHandler; + + private boolean isColumnNameDelimited; + + private String configuredDelimitedColumnName; + + /** + * + */ + public ColumnOverride(String columnName) { + super(); + + this.columnName = columnName; + isColumnNameDelimited = stringContainsSpace(columnName); + } + + public String getColumnName() { + return columnName; + } + + public String getJavaProperty() { + return javaProperty; + } + + public void setJavaProperty(String javaProperty) { + this.javaProperty = javaProperty; + } + + public String getJavaType() { + return javaType; + } + + public void setJavaType(String javaType) { + this.javaType = javaType; + } + + public String getJdbcType() { + return jdbcType; + } + + public void setJdbcType(String jdbcType) { + this.jdbcType = jdbcType; + } + + public String getTypeHandler() { + return typeHandler; + } + + public void setTypeHandler(String typeHandler) { + this.typeHandler = typeHandler; + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("columnOverride"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("column", columnName)); //$NON-NLS-1$ + + if (stringHasValue(javaProperty)) { + xmlElement.addAttribute(new Attribute("property", javaProperty)); //$NON-NLS-1$ + } + + if (stringHasValue(javaType)) { + xmlElement.addAttribute(new Attribute("javaType", javaType)); //$NON-NLS-1$ + } + + if (stringHasValue(jdbcType)) { + xmlElement.addAttribute(new Attribute("jdbcType", jdbcType)); //$NON-NLS-1$ + } + + if (stringHasValue(typeHandler)) { + xmlElement.addAttribute(new Attribute("typeHandler", typeHandler)); //$NON-NLS-1$ + } + + if (stringHasValue(configuredDelimitedColumnName)) { + xmlElement.addAttribute(new Attribute( + "delimitedColumnName", configuredDelimitedColumnName)); //$NON-NLS-1$ + } + + addPropertyXmlElements(xmlElement); + + return xmlElement; + } + + public boolean isColumnNameDelimited() { + return isColumnNameDelimited; + } + + public void setColumnNameDelimited(boolean isColumnNameDelimited) { + this.isColumnNameDelimited = isColumnNameDelimited; + + configuredDelimitedColumnName = isColumnNameDelimited ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + public void validate(List errors, String tableName) { + if (!stringHasValue(columnName)) { + errors.add(getString("ValidationError.22", //$NON-NLS-1$ + tableName)); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnRenamingRule.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnRenamingRule.java new file mode 100644 index 0000000..6f0f9f0 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ColumnRenamingRule.java @@ -0,0 +1,94 @@ +/* + * Copyright 2007 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * This class is used to specify a renaming rule for columns in a table. This + * renaming rule will be run against all column names before calculating the + * corresponding property name. The most common use case is when columns in a + * table are all prefixed by a certain value. + * + * For example, if columns in a table are named: + * + *
    + *
  • CUST_NAME
  • + *
  • CUST_ADDRESS
  • + *
  • CUST_CITY
  • + *
  • CUST_STATE
  • + *
+ * + * it might be annoying to have the generated properties all containing the CUST + * prefix. This class can be used to remove the prefix by specifying + * + *
    + *
  • searchString = "^CUST"
  • + *
  • replaceString=""
  • + *
+ * + * Note that internally, the generator uses the + * java.util.regex.Matcher.replaceAll method for this function. See + * the documentation of that method for example of the regular expression + * language used in Java. + * + * @author Jeff Butler + * + */ +public class ColumnRenamingRule { + private String searchString; + private String replaceString; + + public String getReplaceString() { + return replaceString; + } + + public void setReplaceString(String replaceString) { + this.replaceString = replaceString; + } + + public String getSearchString() { + return searchString; + } + + public void setSearchString(String searchString) { + this.searchString = searchString; + } + + public void validate(List errors, String tableName) { + if (!stringHasValue(searchString)) { + errors.add(getString("ValidationError.14", tableName)); //$NON-NLS-1$ + } + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("columnRenamingRule"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("searchString", searchString)); //$NON-NLS-1$ + + if (replaceString != null) { + xmlElement.addAttribute(new Attribute( + "replaceString", replaceString)); //$NON-NLS-1$ + } + + return xmlElement; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/CommentGeneratorConfiguration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/CommentGeneratorConfiguration.java new file mode 100644 index 0000000..a028a3c --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/CommentGeneratorConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.config; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * @author Jeff Butler + * + */ +public class CommentGeneratorConfiguration extends TypedPropertyHolder { + + /** + * + */ + public CommentGeneratorConfiguration() { + } + + public XmlElement toXmlElement() { + XmlElement answer = new XmlElement("commentGenerator"); //$NON-NLS-1$ + if (getConfigurationType() != null) { + answer.addAttribute(new Attribute("type", getConfigurationType())); //$NON-NLS-1$ + } + + addPropertyXmlElements(answer); + + return answer; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/Configuration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/Configuration.java new file mode 100644 index 0000000..dac3758 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/Configuration.java @@ -0,0 +1,133 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.ArrayList; +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.Document; +import org.mybatis.generator.api.dom.xml.XmlElement; +import org.mybatis.generator.codegen.XmlConstants; +import org.mybatis.generator.exception.InvalidConfigurationException; + +/** + * + * @author Jeff Butler + */ +public class Configuration { + + private List contexts; + private List classPathEntries; + + public Configuration() { + super(); + contexts = new ArrayList(); + classPathEntries = new ArrayList(); + } + + public void addClasspathEntry(String entry) { + classPathEntries.add(entry); + } + + /** + * @return Returns the classPathEntries. + */ + public List getClassPathEntries() { + return classPathEntries; + } + + /** + * This method does a simple validate, it makes sure that all required + * fields have been filled in and that all implementation classes exist and + * are of the proper type. It does not do any more complex operations such + * as: validating that database tables exist or validating that named + * columns exist + */ + public void validate() throws InvalidConfigurationException { + List errors = new ArrayList(); + + for (String classPathEntry : classPathEntries) { + if (!stringHasValue(classPathEntry)) { + errors.add(getString("ValidationError.19")); //$NON-NLS-1$ + // only need to state this error once + break; + } + } + + if (contexts.size() == 0) { + errors.add(getString("ValidationError.11")); //$NON-NLS-1$ + } else { + for (Context context : contexts) { + context.validate(errors); + } + } + + if (errors.size() > 0) { + throw new InvalidConfigurationException(errors); + } + } + + public List getContexts() { + return contexts; + } + + public void addContext(Context context) { + contexts.add(context); + } + + public Context getContext(String id) { + for (Context context : contexts) { + if (id.equals(context.getId())) { + return context; + } + } + + return null; + } + + /** + * Builds an XML representation of this configuration. This can be used to + * persist a programtically generated configuration. + * + * @return the XML representation of this configuration + */ + public Document toDocument() { + // note that this method will not reconstruct a properties + // element - that element is only used in XML parsing + + Document document = new Document( + XmlConstants.MYBATIS_GENERATOR_CONFIG_PUBLIC_ID, + XmlConstants.MYBATIS_GENERATOR_CONFIG_SYSTEM_ID); + XmlElement rootElement = new XmlElement("generatorConfiguration"); //$NON-NLS-1$ + document.setRootElement(rootElement); + + for (String classPathEntry : classPathEntries) { + XmlElement cpeElement = new XmlElement("classPathEntry"); //$NON-NLS-1$ + cpeElement.addAttribute(new Attribute("location", classPathEntry)); //$NON-NLS-1$ + rootElement.addElement(cpeElement); + } + + for (Context context : contexts) { + rootElement.addElement(context.toXmlElement()); + } + + return document; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/GeneratedKey.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/GeneratedKey.java new file mode 100644 index 0000000..8087767 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/GeneratedKey.java @@ -0,0 +1,144 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; +import org.mybatis.generator.internal.db.DatabaseDialects; + +/** + * This class specifies that a key is auto-generated, either as an identity + * column (post insert), or as some other query like a sequences (pre insert). + * + * @author Jeff Butler + */ +public class GeneratedKey { + private String column; + + private String configuredSqlStatement; + + private String runtimeSqlStatement; + + private boolean isIdentity; + + private String type; + + /** + * + */ + public GeneratedKey(String column, String configuredSqlStatement, + boolean isIdentity, String type) { + super(); + this.column = column; + this.type = type; + this.isIdentity = isIdentity; + this.configuredSqlStatement = configuredSqlStatement; + + DatabaseDialects dialect = DatabaseDialects + .getDatabaseDialect(configuredSqlStatement); + if (dialect == null) { + this.runtimeSqlStatement = configuredSqlStatement; + } else { + this.runtimeSqlStatement = dialect.getIdentityRetrievalStatement(); + } + } + + public String getColumn() { + return column; + } + + public boolean isIdentity() { + return isIdentity; + } + + public String getRuntimeSqlStatement() { + return runtimeSqlStatement; + } + + public String getType() { + return type; + } + + /** + * This method is used by the iBATIS2 generators to know + * if the XML element should be placed + * before the insert SQL statement. + * + * @return + */ + public boolean isPlacedBeforeInsertInIbatis2() { + boolean rc; + + if (stringHasValue(type)) { + rc = true; + } else { + rc = !isIdentity; + } + + return rc; + } + + public String getMyBatis3Order() { + return isIdentity ? "AFTER" : "BEFORE"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("generatedKey"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("column", column)); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute( + "sqlStatement", configuredSqlStatement)); //$NON-NLS-1$ + if (stringHasValue(type)) { + xmlElement.addAttribute(new Attribute("type", type)); //$NON-NLS-1$ + } + xmlElement.addAttribute(new Attribute("identity", //$NON-NLS-1$ + isIdentity ? "true" : "false")); //$NON-NLS-1$ //$NON-NLS-2$ + + return xmlElement; + } + + public void validate(List errors, String tableName) { + if (!stringHasValue(runtimeSqlStatement)) { + errors.add(getString("ValidationError.7", //$NON-NLS-1$ + tableName)); + } + + if (stringHasValue(type)) { + if (!"pre".equals(type) && !"post".equals(type)) { //$NON-NLS-1$ //$NON-NLS-2$ + errors.add(getString("ValidationError.15", //$NON-NLS-1$ + tableName)); + } + } + + if ("pre".equals(type) && isIdentity) { //$NON-NLS-1$ + errors.add(getString("ValidationError.23", //$NON-NLS-1$ + tableName)); + } + + if ("post".equals(type) && !isIdentity) { //$NON-NLS-1$ + errors.add(getString("ValidationError.24", //$NON-NLS-1$ + tableName)); + } + } + + public boolean isJdbcStandard() { + return "JDBC".equals(runtimeSqlStatement); //$NON-NLS-1$ + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/IgnoredColumn.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/IgnoredColumn.java new file mode 100644 index 0000000..e791338 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/IgnoredColumn.java @@ -0,0 +1,92 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringContainsSpace; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * @author Jeff Butler + * + */ +public class IgnoredColumn { + + private String columnName; + + private boolean isColumnNameDelimited; + + private String configuredDelimitedColumnName; + + /** + * + */ + public IgnoredColumn(String columnName) { + super(); + this.columnName = columnName; + isColumnNameDelimited = stringContainsSpace(columnName); + } + + public String getColumnName() { + return columnName; + } + + public boolean isColumnNameDelimited() { + return isColumnNameDelimited; + } + + public void setColumnNameDelimited(boolean isColumnNameDelimited) { + this.isColumnNameDelimited = isColumnNameDelimited; + configuredDelimitedColumnName = isColumnNameDelimited ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof IgnoredColumn)) { + return false; + } + + return columnName.equals(((IgnoredColumn) obj).getColumnName()); + } + + public int hashCode() { + return columnName.hashCode(); + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("ignoreColumn"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("column", columnName)); //$NON-NLS-1$ + + if (stringHasValue(configuredDelimitedColumnName)) { + xmlElement.addAttribute(new Attribute( + "delimitedColumnName", configuredDelimitedColumnName)); //$NON-NLS-1$ + } + + return xmlElement; + } + + public void validate(List errors, String tableName) { + if (!stringHasValue(columnName)) { + errors.add(getString("ValidationError.21", //$NON-NLS-1$ + tableName)); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JDBCConnectionConfiguration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JDBCConnectionConfiguration.java new file mode 100644 index 0000000..ceba580 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JDBCConnectionConfiguration.java @@ -0,0 +1,103 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * + * @author Jeff Butler + */ +public class JDBCConnectionConfiguration extends PropertyHolder { + + private String driverClass; + + private String connectionURL; + + private String userId; + + private String password; + + public JDBCConnectionConfiguration() { + super(); + } + + public String getConnectionURL() { + return connectionURL; + } + + public void setConnectionURL(String connectionURL) { + this.connectionURL = connectionURL; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getDriverClass() { + return driverClass; + } + + public void setDriverClass(String driverClass) { + this.driverClass = driverClass; + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("jdbcConnection"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("driverClass", driverClass)); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("connectionURL", connectionURL)); //$NON-NLS-1$ + + if (stringHasValue(userId)) { + xmlElement.addAttribute(new Attribute("userId", userId)); //$NON-NLS-1$ + } + + if (stringHasValue(password)) { + xmlElement.addAttribute(new Attribute("password", password)); //$NON-NLS-1$ + } + + addPropertyXmlElements(xmlElement); + + return xmlElement; + } + + public void validate(List errors) { + if (!stringHasValue(driverClass)) { + errors.add(getString("ValidationError.4")); //$NON-NLS-1$ + } + + if (!stringHasValue(connectionURL)) { + errors.add(getString("ValidationError.5")); //$NON-NLS-1$ + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JavaTypeResolverConfiguration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JavaTypeResolverConfiguration.java new file mode 100644 index 0000000..b68f5bd --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/JavaTypeResolverConfiguration.java @@ -0,0 +1,43 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * @author Jeff Butler + */ +public class JavaTypeResolverConfiguration extends TypedPropertyHolder { + + /** + * + */ + public JavaTypeResolverConfiguration() { + super(); + } + + public XmlElement toXmlElement() { + XmlElement answer = new XmlElement("javaTypeResolver"); //$NON-NLS-1$ + if (getConfigurationType() != null) { + answer.addAttribute(new Attribute("type", getConfigurationType())); //$NON-NLS-1$ + } + + addPropertyXmlElements(answer); + + return answer; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/MergeConstants.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/MergeConstants.java new file mode 100644 index 0000000..49cb33b --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/MergeConstants.java @@ -0,0 +1,40 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +/** + * This class holds constants useful in the XML and Java merging operations. + * + * @author Jeff Butler + * + */ +public class MergeConstants { + + /** + * Utility class - no instances + * + */ + private MergeConstants() { + } + + public static final String[] OLD_XML_ELEMENT_PREFIXES = { + "ibatorgenerated_", "abatorgenerated_" }; //$NON-NLS-1$ //$NON-NLS-2$ + + public static final String NEW_ELEMENT_TAG = "@mbggenerated"; //$NON-NLS-1$ + public static final String[] OLD_ELEMENT_TAGS = { + "@ibatorgenerated", "@abatorgenerated", "@mbggenerated" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ModelType.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ModelType.java new file mode 100644 index 0000000..01d4d45 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/ModelType.java @@ -0,0 +1,56 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +/** + * Typesafe enum of different model types + * + * @author Jeff Butler + */ +public enum ModelType { + HIERARCHICAL("hierarchical"), //$NON-NLS-1$ + FLAT("flat"), //$NON-NLS-1$ + CONDITIONAL("conditional"); //$NON-NLS-1$ + + private final String modelType; + + /** + * + */ + private ModelType(String modelType) { + this.modelType = modelType; + } + + public String getModelType() { + return modelType; + } + + public static ModelType getModelType(String type) { + if (HIERARCHICAL.getModelType().equalsIgnoreCase(type)) { + return HIERARCHICAL; + } else if (FLAT.getModelType().equalsIgnoreCase(type)) { + return FLAT; + } else if (CONDITIONAL.getModelType().equalsIgnoreCase(type)) { + return CONDITIONAL; + } else { + throw new RuntimeException(getString( + "RuntimeError.13", type)); //$NON-NLS-1$ + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PluginConfiguration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PluginConfiguration.java new file mode 100644 index 0000000..a59b1df --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PluginConfiguration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * + * @author Jeff Butler + * + */ +public class PluginConfiguration extends TypedPropertyHolder { + public PluginConfiguration() { + } + + public XmlElement toXmlElement() { + XmlElement answer = new XmlElement("plugin"); //$NON-NLS-1$ + if (getConfigurationType() != null) { + answer.addAttribute(new Attribute("type", getConfigurationType())); //$NON-NLS-1$ + } + + addPropertyXmlElements(answer); + + return answer; + } + + public void validate(List errors, String contextId) { + if (!stringHasValue(getConfigurationType())) { + errors.add(getString("ValidationError.17", //$NON-NLS-1$ + contextId)); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyHolder.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyHolder.java new file mode 100644 index 0000000..c4dd82f --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyHolder.java @@ -0,0 +1,62 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import java.util.Enumeration; +import java.util.Properties; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * @author Jeff Butler + */ +public abstract class PropertyHolder { + private Properties properties; + + /** + * + */ + public PropertyHolder() { + super(); + properties = new Properties(); + } + + public void addProperty(String name, String value) { + properties.setProperty(name, value); + } + + public String getProperty(String name) { + return properties.getProperty(name); + } + + public Properties getProperties() { + return properties; + } + + protected void addPropertyXmlElements(XmlElement xmlElement) { + Enumeration enumeration = properties.propertyNames(); + while (enumeration.hasMoreElements()) { + String propertyName = (String) enumeration.nextElement(); + + XmlElement propertyElement = new XmlElement("property"); //$NON-NLS-1$ + propertyElement.addAttribute(new Attribute("name", propertyName)); //$NON-NLS-1$ + propertyElement.addAttribute(new Attribute( + "value", properties.getProperty(propertyName))); //$NON-NLS-1$ + xmlElement.addElement(propertyElement); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyRegistry.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyRegistry.java new file mode 100644 index 0000000..e4d08de --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/PropertyRegistry.java @@ -0,0 +1,68 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.config; + +/** + * This class holds constants for all properties recognized by the different + * configuration elements. This helps document and maintain the different + * properties, and helps to avoid spelling errors. + * + * @author Jeff Butler + * + */ +public class PropertyRegistry { + public static final String ANY_ENABLE_SUB_PACKAGES = "enableSubPackages"; //$NON-NLS-1$ + + /** + * recognized by table and java model generator + */ + public static final String ANY_ROOT_CLASS = "rootClass"; //$NON-NLS-1$ + public static final String ANY_IMMUTABLE = "immutable"; //$NON-NLS-1$ + public static final String ANY_CONSTRUCTOR_BASED = "constructorBased"; //$NON-NLS-1$ + + /** + * recognized by table and java client generator + */ + public static final String ANY_ROOT_INTERFACE = "rootInterface"; //$NON-NLS-1$ + + public static final String TABLE_USE_COLUMN_INDEXES = "useColumnIndexes"; //$NON-NLS-1$ + public static final String TABLE_USE_ACTUAL_COLUMN_NAMES = "useActualColumnNames"; //$NON-NLS-1$ + public static final String TABLE_USE_COMPOUND_PROPERTY_NAMES = "useCompoundPropertyNames"; //$NON-NLS-1$ + public static final String TABLE_IGNORE_QUALIFIERS_AT_RUNTIME = "ignoreQualifiersAtRuntime"; //$NON-NLS-1$ + public static final String TABLE_RUNTIME_CATALOG = "runtimeCatalog"; //$NON-NLS-1$ + public static final String TABLE_RUNTIME_SCHEMA = "runtimeSchema"; //$NON-NLS-1$ + public static final String TABLE_RUNTIME_TABLE_NAME = "runtimeTableName"; //$NON-NLS-1$ + public static final String TABLE_MODEL_ONLY = "modelOnly"; //$NON-NLS-1$ + public static final String TABLE_SELECT_ALL_ORDER_BY_CLAUSE = "selectAllOrderByClause"; //$NON-NLS-1$ + + public static final String CONTEXT_BEGINNING_DELIMITER = "beginningDelimiter"; //$NON-NLS-1$ + public static final String CONTEXT_ENDING_DELIMITER = "endingDelimiter"; //$NON-NLS-1$ + public static final String CONTEXT_AUTO_DELIMIT_KEYWORDS = "autoDelimitKeywords"; //$NON-NLS-1$ + public static final String CONTEXT_JAVA_FILE_ENCODING = "javaFileEncoding"; //$NON-NLS-1$ + public static final String CONTEXT_JAVA_FORMATTER = "javaFormatter"; //$NON-NLS-1$ + public static final String CONTEXT_XML_FORMATTER = "xmlFormatter"; //$NON-NLS-1$ + + public static final String DAO_EXAMPLE_METHOD_VISIBILITY = "exampleMethodVisibility"; //$NON-NLS-1$ + public static final String DAO_METHOD_NAME_CALCULATOR = "methodNameCalculator"; //$NON-NLS-1$ + + public static final String TYPE_RESOLVER_FORCE_BIG_DECIMALS = "forceBigDecimals"; //$NON-NLS-1$ + + public static final String MODEL_GENERATOR_TRIM_STRINGS = "trimStrings"; //$NON-NLS-1$ + + public static final String COMMENT_GENERATOR_SUPPRESS_DATE = "suppressDate"; //$NON-NLS-1$ + public static final String COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS = "suppressAllComments"; //$NON-NLS-1$ +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TableConfiguration.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TableConfiguration.java new file mode 100644 index 0000000..b06872d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TableConfiguration.java @@ -0,0 +1,544 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +import static org.mybatis.generator.internal.util.EqualsUtil.areEqual; +import static org.mybatis.generator.internal.util.HashCodeUtil.hash; +import static org.mybatis.generator.internal.util.HashCodeUtil.SEED; +import static org.mybatis.generator.internal.util.messages.Messages.getString; +import static org.mybatis.generator.internal.util.StringUtility.composeFullyQualifiedTableName; +import static org.mybatis.generator.internal.util.StringUtility.isTrue; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.mybatis.generator.api.dom.xml.Attribute; +import org.mybatis.generator.api.dom.xml.XmlElement; + +/** + * + * @author Jeff Butler + */ +public class TableConfiguration extends PropertyHolder { + private boolean insertStatementEnabled; + + private boolean selectByPrimaryKeyStatementEnabled; + + private boolean selectByExampleStatementEnabled; + + private boolean updateByPrimaryKeyStatementEnabled; + + private boolean deleteByPrimaryKeyStatementEnabled; + + private boolean deleteByExampleStatementEnabled; + + private boolean countByExampleStatementEnabled; + + private boolean updateByExampleStatementEnabled; + + private List columnOverrides; + + private Map ignoredColumns; + + private GeneratedKey generatedKey; + + private String selectByPrimaryKeyQueryId; + + private String selectByExampleQueryId; + + private String catalog; + private String schema; + private String tableName; + private String domainObjectName; + private String alias; + private ModelType modelType; + private boolean wildcardEscapingEnabled; + private String configuredModelType; + private boolean delimitIdentifiers; + + private ColumnRenamingRule columnRenamingRule; + private boolean isAllColumnDelimitingEnabled; + + public TableConfiguration(Context context) { + super(); + + this.modelType = context.getDefaultModelType(); + + columnOverrides = new ArrayList(); + ignoredColumns = new HashMap(); + + insertStatementEnabled = true; + selectByPrimaryKeyStatementEnabled = true; + selectByExampleStatementEnabled = true; + updateByPrimaryKeyStatementEnabled = true; + deleteByPrimaryKeyStatementEnabled = true; + deleteByExampleStatementEnabled = true; + countByExampleStatementEnabled = true; + updateByExampleStatementEnabled = true; + } + + public boolean isDeleteByPrimaryKeyStatementEnabled() { + return deleteByPrimaryKeyStatementEnabled; + } + + public void setDeleteByPrimaryKeyStatementEnabled( + boolean deleteByPrimaryKeyStatementEnabled) { + this.deleteByPrimaryKeyStatementEnabled = deleteByPrimaryKeyStatementEnabled; + } + + public boolean isInsertStatementEnabled() { + return insertStatementEnabled; + } + + public void setInsertStatementEnabled(boolean insertStatementEnabled) { + this.insertStatementEnabled = insertStatementEnabled; + } + + public boolean isSelectByPrimaryKeyStatementEnabled() { + return selectByPrimaryKeyStatementEnabled; + } + + public void setSelectByPrimaryKeyStatementEnabled( + boolean selectByPrimaryKeyStatementEnabled) { + this.selectByPrimaryKeyStatementEnabled = selectByPrimaryKeyStatementEnabled; + } + + public boolean isUpdateByPrimaryKeyStatementEnabled() { + return updateByPrimaryKeyStatementEnabled; + } + + public void setUpdateByPrimaryKeyStatementEnabled( + boolean updateByPrimaryKeyStatementEnabled) { + this.updateByPrimaryKeyStatementEnabled = updateByPrimaryKeyStatementEnabled; + } + + public boolean isColumnIgnored(String columnName) { + for (Map.Entry entry : ignoredColumns + .entrySet()) { + IgnoredColumn ic = entry.getKey(); + if (ic.isColumnNameDelimited()) { + if (columnName.equals(ic.getColumnName())) { + entry.setValue(Boolean.TRUE); + return true; + } + } else { + if (columnName.equalsIgnoreCase(ic.getColumnName())) { + entry.setValue(Boolean.TRUE); + return true; + } + } + } + + return false; + } + + public void addIgnoredColumn(IgnoredColumn ignoredColumn) { + ignoredColumns.put(ignoredColumn, Boolean.FALSE); + } + + public void addColumnOverride(ColumnOverride columnOverride) { + columnOverrides.add(columnOverride); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof TableConfiguration)) { + return false; + } + + TableConfiguration other = (TableConfiguration) obj; + + return areEqual(this.catalog, other.catalog) + && areEqual(this.schema, other.schema) + && areEqual(this.tableName, other.tableName); + } + + @Override + public int hashCode() { + int result = SEED; + result = hash(result, catalog); + result = hash(result, schema); + result = hash(result, tableName); + + return result; + } + + public boolean isSelectByExampleStatementEnabled() { + return selectByExampleStatementEnabled; + } + + public void setSelectByExampleStatementEnabled( + boolean selectByExampleStatementEnabled) { + this.selectByExampleStatementEnabled = selectByExampleStatementEnabled; + } + + /** + * May return null if the column has not been overridden + * + * @param columnName + * @return the column override (if any) related to this column + */ + public ColumnOverride getColumnOverride(String columnName) { + for (ColumnOverride co : columnOverrides) { + if (co.isColumnNameDelimited()) { + if (columnName.equals(co.getColumnName())) { + return co; + } + } else { + if (columnName.equalsIgnoreCase(co.getColumnName())) { + return co; + } + } + } + + return null; + } + + public GeneratedKey getGeneratedKey() { + return generatedKey; + } + + public String getSelectByExampleQueryId() { + return selectByExampleQueryId; + } + + public void setSelectByExampleQueryId(String selectByExampleQueryId) { + this.selectByExampleQueryId = selectByExampleQueryId; + } + + public String getSelectByPrimaryKeyQueryId() { + return selectByPrimaryKeyQueryId; + } + + public void setSelectByPrimaryKeyQueryId(String selectByPrimaryKeyQueryId) { + this.selectByPrimaryKeyQueryId = selectByPrimaryKeyQueryId; + } + + public boolean isDeleteByExampleStatementEnabled() { + return deleteByExampleStatementEnabled; + } + + public void setDeleteByExampleStatementEnabled( + boolean deleteByExampleStatementEnabled) { + this.deleteByExampleStatementEnabled = deleteByExampleStatementEnabled; + } + + public boolean areAnyStatementsEnabled() { + return selectByExampleStatementEnabled + || selectByPrimaryKeyStatementEnabled || insertStatementEnabled + || updateByPrimaryKeyStatementEnabled + || deleteByExampleStatementEnabled + || deleteByPrimaryKeyStatementEnabled + || countByExampleStatementEnabled + || updateByExampleStatementEnabled; + } + + public void setGeneratedKey(GeneratedKey generatedKey) { + this.generatedKey = generatedKey; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getCatalog() { + return catalog; + } + + public void setCatalog(String catalog) { + this.catalog = catalog; + } + + public String getDomainObjectName() { + return domainObjectName; + } + + public void setDomainObjectName(String domainObjectName) { + this.domainObjectName = domainObjectName; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public List getColumnOverrides() { + return columnOverrides; + } + + /** + * This method returns an iterator of Strings. The values are the columns + * that were specified to be ignored in the table, but do not exist in the + * table. + * + * @return an List of Strings - the columns that were improperly configured + * as ignored columns + */ + public List getIgnoredColumnsInError() { + List answer = new ArrayList(); + + for (Map.Entry entry : ignoredColumns + .entrySet()) { + if (Boolean.FALSE.equals(entry.getValue())) { + answer.add(entry.getKey().getColumnName()); + } + } + + return answer; + } + + public ModelType getModelType() { + return modelType; + } + + public void setConfiguredModelType(String configuredModelType) { + this.configuredModelType = configuredModelType; + this.modelType = ModelType.getModelType(configuredModelType); + } + + public boolean isWildcardEscapingEnabled() { + return wildcardEscapingEnabled; + } + + public void setWildcardEscapingEnabled(boolean wildcardEscapingEnabled) { + this.wildcardEscapingEnabled = wildcardEscapingEnabled; + } + + public XmlElement toXmlElement() { + XmlElement xmlElement = new XmlElement("table"); //$NON-NLS-1$ + xmlElement.addAttribute(new Attribute("tableName", tableName)); //$NON-NLS-1$ + + if (stringHasValue(catalog)) { + xmlElement.addAttribute(new Attribute("catalog", catalog)); //$NON-NLS-1$ + } + + if (stringHasValue(schema)) { + xmlElement.addAttribute(new Attribute("schema", schema)); //$NON-NLS-1$ + } + + if (stringHasValue(alias)) { + xmlElement.addAttribute(new Attribute("alias", alias)); //$NON-NLS-1$ + } + + if (stringHasValue(domainObjectName)) { + xmlElement.addAttribute(new Attribute( + "domainObjectName", domainObjectName)); //$NON-NLS-1$ + } + + if (!insertStatementEnabled) { + xmlElement.addAttribute(new Attribute("enableInsert", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!selectByPrimaryKeyStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableSelectByPrimaryKey", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!selectByExampleStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableSelectByExample", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!updateByPrimaryKeyStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableUpdateByPrimaryKey", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!deleteByPrimaryKeyStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableDeleteByPrimaryKey", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!deleteByExampleStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableDeleteByExample", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!countByExampleStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableCountByExample", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (!updateByExampleStatementEnabled) { + xmlElement.addAttribute(new Attribute( + "enableUpdateByExample", "false")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (stringHasValue(selectByPrimaryKeyQueryId)) { + xmlElement.addAttribute(new Attribute( + "selectByPrimaryKeyQueryId", selectByPrimaryKeyQueryId)); //$NON-NLS-1$ + } + + if (stringHasValue(selectByExampleQueryId)) { + xmlElement.addAttribute(new Attribute( + "selectByExampleQueryId", selectByExampleQueryId)); //$NON-NLS-1$ + } + + if (configuredModelType != null) { + xmlElement.addAttribute(new Attribute( + "modelType", configuredModelType)); //$NON-NLS-1$ + } + + if (wildcardEscapingEnabled) { + xmlElement.addAttribute(new Attribute("escapeWildcards", "true")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (isAllColumnDelimitingEnabled) { + xmlElement.addAttribute(new Attribute("delimitAllColumns", "true")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (delimitIdentifiers) { + xmlElement + .addAttribute(new Attribute("delimitIdentifiers", "true")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + addPropertyXmlElements(xmlElement); + + if (generatedKey != null) { + xmlElement.addElement(generatedKey.toXmlElement()); + } + + if (columnRenamingRule != null) { + xmlElement.addElement(columnRenamingRule.toXmlElement()); + } + + if (ignoredColumns.size() > 0) { + for (IgnoredColumn ignoredColumn : ignoredColumns.keySet()) { + xmlElement.addElement(ignoredColumn.toXmlElement()); + } + } + + if (columnOverrides.size() > 0) { + for (ColumnOverride columnOverride : columnOverrides) { + xmlElement.addElement(columnOverride.toXmlElement()); + } + } + + return xmlElement; + } + + @Override + public String toString() { + return composeFullyQualifiedTableName(catalog, schema, + tableName, '.'); + } + + public boolean isDelimitIdentifiers() { + return delimitIdentifiers; + } + + public void setDelimitIdentifiers(boolean delimitIdentifiers) { + this.delimitIdentifiers = delimitIdentifiers; + } + + public boolean isCountByExampleStatementEnabled() { + return countByExampleStatementEnabled; + } + + public void setCountByExampleStatementEnabled( + boolean countByExampleStatementEnabled) { + this.countByExampleStatementEnabled = countByExampleStatementEnabled; + } + + public boolean isUpdateByExampleStatementEnabled() { + return updateByExampleStatementEnabled; + } + + public void setUpdateByExampleStatementEnabled( + boolean updateByExampleStatementEnabled) { + this.updateByExampleStatementEnabled = updateByExampleStatementEnabled; + } + + public void validate(List errors, int listPosition) { + if (!stringHasValue(tableName)) { + errors.add(getString( + "ValidationError.6", Integer.toString(listPosition))); //$NON-NLS-1$ + } + + String fqTableName = composeFullyQualifiedTableName( + catalog, schema, tableName, '.'); + + if (generatedKey != null) { + generatedKey.validate(errors, fqTableName); + } + + if (isTrue(getProperty(PropertyRegistry.TABLE_USE_COLUMN_INDEXES))) { + // when using column indexes, either both or neither query ids + // should be set + if (selectByExampleStatementEnabled + && selectByPrimaryKeyStatementEnabled) { + boolean queryId1Set = stringHasValue(selectByExampleQueryId); + boolean queryId2Set = stringHasValue(selectByPrimaryKeyQueryId); + + if (queryId1Set != queryId2Set) { + errors.add(getString("ValidationError.13", //$NON-NLS-1$ + fqTableName)); + } + } + } + + if (columnRenamingRule != null) { + columnRenamingRule.validate(errors, fqTableName); + } + + for (ColumnOverride columnOverride : columnOverrides) { + columnOverride.validate(errors, fqTableName); + } + + for (IgnoredColumn ignoredColumn : ignoredColumns.keySet()) { + ignoredColumn.validate(errors, fqTableName); + } + } + + public ColumnRenamingRule getColumnRenamingRule() { + return columnRenamingRule; + } + + public void setColumnRenamingRule(ColumnRenamingRule columnRenamingRule) { + this.columnRenamingRule = columnRenamingRule; + } + + public boolean isAllColumnDelimitingEnabled() { + return isAllColumnDelimitingEnabled; + } + + public void setAllColumnDelimitingEnabled( + boolean isAllColumnDelimitingEnabled) { + this.isAllColumnDelimitingEnabled = isAllColumnDelimitingEnabled; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TypedPropertyHolder.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TypedPropertyHolder.java new file mode 100644 index 0000000..13f3dc6 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/TypedPropertyHolder.java @@ -0,0 +1,48 @@ +/* + * Copyright 2005, 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config; + +/** + * @author Jeff Butler + */ +public abstract class TypedPropertyHolder extends PropertyHolder { + + private String configurationType; + + /** + * + */ + public TypedPropertyHolder() { + super(); + } + + public String getConfigurationType() { + return configurationType; + } + + /** + * Sets the value of the type specified in the configuration. If the special + * value DEFAULT is specified, then the value will be ignored. + * + * @param configurationType + * the type specified in the configuration + */ + public void setConfigurationType(String configurationType) { + if (!"DEFAULT".equalsIgnoreCase(configurationType)) { //$NON-NLS-1$ + this.configurationType = configurationType; + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ConfigurationParser.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ConfigurationParser.java new file mode 100644 index 0000000..c318f90 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ConfigurationParser.java @@ -0,0 +1,163 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config.xml; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.mybatis.generator.codegen.XmlConstants; +import org.mybatis.generator.config.Configuration; +import org.mybatis.generator.exception.XMLParserException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +public class ConfigurationParser { + + private List warnings; + private List parseErrors; + private Properties properties; + + public ConfigurationParser(List warnings) { + this(null, warnings); + } + + public ConfigurationParser(Properties properties, List warnings) { + super(); + if (properties == null) { + this.properties = System.getProperties(); + } else { + this.properties = properties; + } + + if (warnings == null) { + this.warnings = new ArrayList(); + } else { + this.warnings = warnings; + } + + parseErrors = new ArrayList(); + } + + public Configuration parseConfiguration(File inputFile) throws IOException, + XMLParserException { + + FileReader fr = new FileReader(inputFile); + + return parseConfiguration(fr); + } + + public Configuration parseConfiguration(Reader reader) throws IOException, + XMLParserException { + + InputSource is = new InputSource(reader); + + return parseConfiguration(is); + } + + public Configuration parseConfiguration(InputStream inputStream) + throws IOException, XMLParserException { + + InputSource is = new InputSource(inputStream); + + return parseConfiguration(is); + } + + private Configuration parseConfiguration(InputSource inputSource) + throws IOException, XMLParserException { + parseErrors.clear(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setValidating(true); + + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new ParserEntityResolver()); + + ParserErrorHandler handler = new ParserErrorHandler(warnings, + parseErrors); + builder.setErrorHandler(handler); + + Document document = null; + try { + document = builder.parse(inputSource); + } catch (SAXParseException e) { + throw new XMLParserException(parseErrors); + } catch (SAXException e) { + if (e.getException() == null) { + parseErrors.add(e.getMessage()); + } else { + parseErrors.add(e.getException().getMessage()); + } + } + + if (parseErrors.size() > 0) { + throw new XMLParserException(parseErrors); + } + + Configuration config; + Element rootNode = document.getDocumentElement(); + DocumentType docType = document.getDoctype(); + if (rootNode.getNodeType() == Node.ELEMENT_NODE + && docType.getPublicId().equals( + XmlConstants.IBATOR_CONFIG_PUBLIC_ID)) { + config = parseIbatorConfiguration(rootNode); + } else if (rootNode.getNodeType() == Node.ELEMENT_NODE + && docType.getPublicId().equals( + XmlConstants.MYBATIS_GENERATOR_CONFIG_PUBLIC_ID)) { + config = parseMyBatisGeneratorConfiguration(rootNode); + } else { + throw new XMLParserException(getString("RuntimeError.5")); //$NON-NLS-1$ + } + + if (parseErrors.size() > 0) { + throw new XMLParserException(parseErrors); + } + + return config; + } catch (ParserConfigurationException e) { + parseErrors.add(e.getMessage()); + throw new XMLParserException(parseErrors); + } + } + + private Configuration parseIbatorConfiguration(Element rootNode) + throws XMLParserException { + IbatorConfigurationParser parser = new IbatorConfigurationParser( + properties); + return parser.parseIbatorConfiguration(rootNode); + } + + private Configuration parseMyBatisGeneratorConfiguration(Element rootNode) + throws XMLParserException { + MyBatisGeneratorConfigurationParser parser = new MyBatisGeneratorConfigurationParser( + properties); + return parser.parseConfiguration(rootNode); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserEntityResolver.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserEntityResolver.java new file mode 100644 index 0000000..5fdce25 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserEntityResolver.java @@ -0,0 +1,65 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config.xml; + +import java.io.IOException; +import java.io.InputStream; + +import org.mybatis.generator.codegen.XmlConstants; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * @author Jeff Butler + */ +public class ParserEntityResolver implements EntityResolver { + + /** + * + */ + public ParserEntityResolver() { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, + * java.lang.String) + */ + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + if (XmlConstants.IBATOR_CONFIG_PUBLIC_ID.equalsIgnoreCase(publicId)) { + InputStream is = getClass().getClassLoader().getResourceAsStream( + "org/mybatis/generator/config/xml/ibator-config_1_0.dtd"); //$NON-NLS-1$ + InputSource ins = new InputSource(is); + + return ins; + } else if (XmlConstants.MYBATIS_GENERATOR_CONFIG_PUBLIC_ID + .equalsIgnoreCase(publicId)) { + InputStream is = getClass() + .getClassLoader() + .getResourceAsStream( + "org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd"); //$NON-NLS-1$ + InputSource ins = new InputSource(is); + + return ins; + } else { + return null; + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserErrorHandler.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserErrorHandler.java new file mode 100644 index 0000000..0d7a025 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ParserErrorHandler.java @@ -0,0 +1,75 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.config.xml; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * @author Jeff Butler + */ +public class ParserErrorHandler implements ErrorHandler { + private List warnings; + + private List errors; + + /** + * + */ + public ParserErrorHandler(List warnings, List errors) { + super(); + this.warnings = warnings; + this.errors = errors; + } + + /* + * (non-Javadoc) + * + * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) + */ + public void warning(SAXParseException exception) throws SAXException { + warnings.add(getString("Warning.7", //$NON-NLS-1$ + Integer.toString(exception.getLineNumber()), exception + .getMessage())); + } + + /* + * (non-Javadoc) + * + * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException) + */ + public void error(SAXParseException exception) throws SAXException { + errors.add(getString("RuntimeError.4", //$NON-NLS-1$ + Integer.toString(exception.getLineNumber()), exception + .getMessage())); + } + + /* + * (non-Javadoc) + * + * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException) + */ + public void fatalError(SAXParseException exception) throws SAXException { + errors.add(getString("RuntimeError.4", //$NON-NLS-1$ + Integer.toString(exception.getLineNumber()), exception + .getMessage())); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ibator-config_1_0.dtd b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ibator-config_1_0.dtd new file mode 100644 index 0000000..9c546f6 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/ibator-config_1_0.dtd @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd new file mode 100644 index 0000000..1612bf8 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/config/xml/mybatis-generator-config_1_0.dtd @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/InvalidConfigurationException.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/InvalidConfigurationException.java new file mode 100644 index 0000000..fa3f996 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/InvalidConfigurationException.java @@ -0,0 +1,48 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.exception; + +import java.util.List; + +/** + * @author Jeff Butler + */ +public class InvalidConfigurationException extends Exception { + static final long serialVersionUID = 4902307610148543411L; + + private List errors; + + /** + * + */ + public InvalidConfigurationException(List errors) { + super(); + this.errors = errors; + } + + public List getErrors() { + return errors; + } + + @Override + public String getMessage() { + if (errors != null && errors.size() > 0) { + return errors.get(0); + } + + return super.getMessage(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/ShellException.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/ShellException.java new file mode 100644 index 0000000..1ccd384 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/ShellException.java @@ -0,0 +1,55 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.exception; + +/** + * This class is used by the ShellCallback methods to denote unrecoverable + * errors. + * + * @author Jeff Butler + */ +public class ShellException extends Exception { + static final long serialVersionUID = -2026841561754434544L; + + /** + * + */ + public ShellException() { + super(); + } + + /** + * @param arg0 + */ + public ShellException(String arg0) { + super(arg0); + } + + /** + * @param arg0 + * @param arg1 + */ + public ShellException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + /** + * @param arg0 + */ + public ShellException(Throwable arg0) { + super(arg0); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/XMLParserException.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/XMLParserException.java new file mode 100644 index 0000000..e70d40a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/exception/XMLParserException.java @@ -0,0 +1,56 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.exception; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jeff Butler + */ +public class XMLParserException extends Exception { + + private static final long serialVersionUID = 5172525430401340573L; + + private List errors; + + /** + * + */ + public XMLParserException(List errors) { + super(); + this.errors = errors; + } + + public XMLParserException(String error) { + super(error); + this.errors = new ArrayList(); + errors.add(error); + } + + public List getErrors() { + return errors; + } + + @Override + public String getMessage() { + if (errors != null && errors.size() > 0) { + return errors.get(0); + } + + return super.getMessage(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java new file mode 100644 index 0000000..85ac8cc --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java @@ -0,0 +1,344 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal; + +import static org.mybatis.generator.internal.util.StringUtility.isTrue; + +import java.util.Date; +import java.util.Properties; + +import org.mybatis.generator.api.CommentGenerator; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.CompilationUnit; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.InnerClass; +import org.mybatis.generator.api.dom.java.InnerEnum; +import org.mybatis.generator.api.dom.java.JavaElement; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.xml.TextElement; +import org.mybatis.generator.api.dom.xml.XmlElement; +import org.mybatis.generator.config.MergeConstants; +import org.mybatis.generator.config.PropertyRegistry; + +/** + * @author Jeff Butler + * + */ +public class DefaultCommentGenerator implements CommentGenerator { + + private Properties properties; + private boolean suppressDate; + private boolean suppressAllComments; + + public DefaultCommentGenerator() { + super(); + properties = new Properties(); + suppressDate = false; + suppressAllComments = false; + } + + public void addJavaFileComment(CompilationUnit compilationUnit) { + // add no file level comments by default + return; + } + + /** + * Adds a suitable comment to warn users that the element was generated, and + * when it was generated. + */ + public void addComment(XmlElement xmlElement) { + if (suppressAllComments) { + return; + } + + xmlElement.addElement(new TextElement("")); //$NON-NLS-1$ + } + + public void addRootComment(XmlElement rootElement) { + // add no document level comments by default + return; + } + + public void addConfigurationProperties(Properties properties) { + this.properties.putAll(properties); + + suppressDate = isTrue(properties + .getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE)); + + suppressAllComments = isTrue(properties + .getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS)); + } + + /** + * This method adds the custom javadoc tag for. You may do nothing if you do + * not wish to include the Javadoc tag - however, if you do not include the + * Javadoc tag then the Java merge capability of the eclipse plugin will + * break. + * + * @param javaElement + * the java element + */ + protected void addJavadocTag(JavaElement javaElement, + boolean markAsDoNotDelete) { + javaElement.addJavaDocLine(" *"); //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + sb.append(" * "); //$NON-NLS-1$ + sb.append(MergeConstants.NEW_ELEMENT_TAG); + if (markAsDoNotDelete) { + sb.append(" do_not_delete_during_merge"); //$NON-NLS-1$ + } + String s = getDateString(); + if (s != null) { + sb.append(' '); + sb.append(s); + } + javaElement.addJavaDocLine(sb.toString()); + } + + /** + * This method returns a formated date string to include in the Javadoc tag + * and XML comments. You may return null if you do not want the date in + * these documentation elements. + * + * @return a string representing the current timestamp, or null + */ + protected String getDateString() { + if (suppressDate) { + return null; + } else { + return new Date().toString(); + } + } + + public void addClassComment(InnerClass innerClass, + IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + innerClass.addJavaDocLine("/**"); //$NON-NLS-1$ + innerClass + .addJavaDocLine(" * This class was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This class corresponds to the database table "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + innerClass.addJavaDocLine(sb.toString()); + + addJavadocTag(innerClass, false); + + innerClass.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addEnumComment(InnerEnum innerEnum, + IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + innerEnum.addJavaDocLine("/**"); //$NON-NLS-1$ + innerEnum + .addJavaDocLine(" * This enum was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This enum corresponds to the database table "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + innerEnum.addJavaDocLine(sb.toString()); + + addJavadocTag(innerEnum, false); + + innerEnum.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addFieldComment(Field field, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + field.addJavaDocLine("/**"); //$NON-NLS-1$ + field + .addJavaDocLine(" * This field was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This field corresponds to the database column "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + sb.append('.'); + sb.append(introspectedColumn.getActualColumnName()); + field.addJavaDocLine(sb.toString()); + + addJavadocTag(field, false); + + field.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addFieldComment(Field field, IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + field.addJavaDocLine("/**"); //$NON-NLS-1$ + field + .addJavaDocLine(" * This field was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This field corresponds to the database table "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + field.addJavaDocLine(sb.toString()); + + addJavadocTag(field, false); + + field.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addGeneralMethodComment(Method method, + IntrospectedTable introspectedTable) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + method.addJavaDocLine("/**"); //$NON-NLS-1$ + method + .addJavaDocLine(" * This method was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This method corresponds to the database table "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + method.addJavaDocLine(sb.toString()); + + addJavadocTag(method, false); + + method.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addGetterComment(Method method, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + method.addJavaDocLine("/**"); //$NON-NLS-1$ + method + .addJavaDocLine(" * This method was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This method returns the value of the database column "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + sb.append('.'); + sb.append(introspectedColumn.getActualColumnName()); + method.addJavaDocLine(sb.toString()); + + method.addJavaDocLine(" *"); //$NON-NLS-1$ + + sb.setLength(0); + sb.append(" * @return the value of "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + sb.append('.'); + sb.append(introspectedColumn.getActualColumnName()); + method.addJavaDocLine(sb.toString()); + + addJavadocTag(method, false); + + method.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addSetterComment(Method method, + IntrospectedTable introspectedTable, + IntrospectedColumn introspectedColumn) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + method.addJavaDocLine("/**"); //$NON-NLS-1$ + method + .addJavaDocLine(" * This method was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This method sets the value of the database column "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + sb.append('.'); + sb.append(introspectedColumn.getActualColumnName()); + method.addJavaDocLine(sb.toString()); + + method.addJavaDocLine(" *"); //$NON-NLS-1$ + + Parameter parm = method.getParameters().get(0); + sb.setLength(0); + sb.append(" * @param "); //$NON-NLS-1$ + sb.append(parm.getName()); + sb.append(" the value for "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + sb.append('.'); + sb.append(introspectedColumn.getActualColumnName()); + method.addJavaDocLine(sb.toString()); + + addJavadocTag(method, false); + + method.addJavaDocLine(" */"); //$NON-NLS-1$ + } + + public void addClassComment(InnerClass innerClass, + IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { + if (suppressAllComments) { + return; + } + + StringBuilder sb = new StringBuilder(); + + innerClass.addJavaDocLine("/**"); //$NON-NLS-1$ + innerClass + .addJavaDocLine(" * This class was generated by MyBatis Generator."); //$NON-NLS-1$ + + sb.append(" * This class corresponds to the database table "); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable()); + innerClass.addJavaDocLine(sb.toString()); + + addJavadocTag(innerClass, markAsDoNotDelete); + + innerClass.addJavaDocLine(" */"); //$NON-NLS-1$ + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultDAOMethodNameCalculator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultDAOMethodNameCalculator.java new file mode 100644 index 0000000..7f23df3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DefaultDAOMethodNameCalculator.java @@ -0,0 +1,172 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal; + +import org.mybatis.generator.api.DAOMethodNameCalculator; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.internal.rules.Rules; + +/** + * @author Jeff Butler + * + */ +public class DefaultDAOMethodNameCalculator implements DAOMethodNameCalculator { + + /** + * + */ + public DefaultDAOMethodNameCalculator() { + super(); + } + + public String getInsertMethodName(IntrospectedTable introspectedTable) { + return "insert"; //$NON-NLS-1$ + } + + /** + * 1. if this will be the only updateByPrimaryKey, then the result should be + * updateByPrimaryKey. 2. If the other method is enabled, but there are + * seperate base and blob classes, then the method name should be + * updateByPrimaryKey 3. Else the method name should be + * updateByPrimaryKeyWithoutBLOBs + */ + public String getUpdateByPrimaryKeyWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByPrimaryKeyWithBLOBs()) { + return "updateByPrimaryKey"; //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + return "updateByPrimaryKey"; //$NON-NLS-1$ + } else { + return "updateByPrimaryKeyWithoutBLOBs"; //$NON-NLS-1$ + } + } + + /** + * 1. if this will be the only updateByPrimaryKey, then the result should be + * updateByPrimaryKey. 2. If the other method is enabled, but there are + * seperate base and blob classes, then the method name should be + * updateByPrimaryKey 3. Else the method name should be + * updateByPrimaryKeyWithBLOBs + */ + public String getUpdateByPrimaryKeyWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByPrimaryKeyWithoutBLOBs()) { + return "updateByPrimaryKey"; //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + return "updateByPrimaryKey"; //$NON-NLS-1$ + } else { + return "updateByPrimaryKeyWithBLOBs"; //$NON-NLS-1$ + } + } + + public String getDeleteByExampleMethodName( + IntrospectedTable introspectedTable) { + return "deleteByExample"; //$NON-NLS-1$ + } + + public String getDeleteByPrimaryKeyMethodName( + IntrospectedTable introspectedTable) { + return "deleteByPrimaryKey"; //$NON-NLS-1$ + } + + /** + * 1. if this will be the only selectByExample, then the result should be + * selectByExample. 2. Else the method name should be + * selectByExampleWithoutBLOBs + */ + public String getSelectByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateSelectByExampleWithBLOBs()) { + return "selectByExample"; //$NON-NLS-1$ + } else { + return "selectByExampleWithoutBLOBs"; //$NON-NLS-1$ + } + } + + /** + * 1. if this will be the only selectByExample, then the result should be + * selectByExample. 2. Else the method name should be + * selectByExampleWithBLOBs + */ + public String getSelectByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateSelectByExampleWithoutBLOBs()) { + return "selectByExample"; //$NON-NLS-1$ + } else { + return "selectByExampleWithBLOBs"; //$NON-NLS-1$ + } + } + + public String getSelectByPrimaryKeyMethodName( + IntrospectedTable introspectedTable) { + return "selectByPrimaryKey"; //$NON-NLS-1$ + } + + public String getUpdateByPrimaryKeySelectiveMethodName( + IntrospectedTable introspectedTable) { + return "updateByPrimaryKeySelective"; //$NON-NLS-1$ + } + + public String getCountByExampleMethodName( + IntrospectedTable introspectedTable) { + return "countByExample"; //$NON-NLS-1$ + } + + public String getUpdateByExampleSelectiveMethodName( + IntrospectedTable introspectedTable) { + return "updateByExampleSelective"; //$NON-NLS-1$ + } + + public String getUpdateByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByExampleWithoutBLOBs()) { + return "updateByExample"; //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + return "updateByExample"; //$NON-NLS-1$ + } else { + return "updateByExampleWithBLOBs"; //$NON-NLS-1$ + } + } + + public String getUpdateByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByExampleWithBLOBs()) { + return "updateByExample"; //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + return "updateByExample"; //$NON-NLS-1$ + } else { + return "updateByExampleWithoutBLOBs"; //$NON-NLS-1$ + } + } + + public String getInsertSelectiveMethodName( + IntrospectedTable introspectedTable) { + return "insertSelective"; //$NON-NLS-1$ + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DomWriter.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DomWriter.java new file mode 100644 index 0000000..23be590 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/DomWriter.java @@ -0,0 +1,341 @@ +/* + * Copyright 2007 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Method; + +import org.mybatis.generator.exception.ShellException; +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; + +/** + * This class is used to generate a String representation of an XML document. It + * is very much based on the class dom.Writer from the Apache Xerces examples, + * but I've simplified and updated it. + * + * @author Andy Clark, IBM (Original work) + * @author Jeff Butler (derivation) + */ +public class DomWriter { + protected PrintWriter printWriter; + + protected boolean isXML11; + + public DomWriter() { + super(); + } + + public synchronized String toString(Document document) + throws ShellException { + StringWriter sw = new StringWriter(); + printWriter = new PrintWriter(sw); + write(document); + String s = sw.toString(); + return s; + } + + /** Returns a sorted list of attributes. */ + protected Attr[] sortAttributes(NamedNodeMap attrs) { + + int len = (attrs != null) ? attrs.getLength() : 0; + Attr array[] = new Attr[len]; + for (int i = 0; i < len; i++) { + array[i] = (Attr) attrs.item(i); + } + for (int i = 0; i < len - 1; i++) { + String name = array[i].getNodeName(); + int index = i; + for (int j = i + 1; j < len; j++) { + String curName = array[j].getNodeName(); + if (curName.compareTo(name) < 0) { + name = curName; + index = j; + } + } + if (index != i) { + Attr temp = array[i]; + array[i] = array[index]; + array[index] = temp; + } + } + + return array; + + } + + /** Normalizes and prints the given string. */ + protected void normalizeAndPrint(String s, boolean isAttValue) { + + int len = (s != null) ? s.length() : 0; + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + normalizeAndPrint(c, isAttValue); + } + + } + + /** Normalizes and print the given character. */ + protected void normalizeAndPrint(char c, boolean isAttValue) { + + switch (c) { + case '<': { + printWriter.print("<"); //$NON-NLS-1$ + break; + } + case '>': { + printWriter.print(">"); //$NON-NLS-1$ + break; + } + case '&': { + printWriter.print("&"); //$NON-NLS-1$ + break; + } + case '"': { + // A '"' that appears in character data + // does not need to be escaped. + if (isAttValue) { + printWriter.print("""); //$NON-NLS-1$ + } else { + printWriter.print('"'); + } + break; + } + case '\r': { + // If CR is part of the document's content, it + // must not be printed as a literal otherwise + // it would be normalized to LF when the document + // is reparsed. + printWriter.print(" "); //$NON-NLS-1$ + break; + } + default: { + // In XML 1.1, control chars in the ranges [#x1-#x1F, #x7F-#x9F] + // must be escaped. + // + // Escape space characters that would be normalized to #x20 in + // attribute values + // when the document is reparsed. + // + // Escape NEL (0x85) and LSEP (0x2028) that appear in content + // if the document is XML 1.1, since they would be normalized to LF + // when the document is reparsed. + if (isXML11 + && ((c >= 0x01 && c <= 0x1F && c != 0x09 && c != 0x0A) + || (c >= 0x7F && c <= 0x9F) || c == 0x2028) + || isAttValue && (c == 0x09 || c == 0x0A)) { + printWriter.print("&#x"); //$NON-NLS-1$ + printWriter.print(Integer.toHexString(c).toUpperCase()); + printWriter.print(';'); + } else { + printWriter.print(c); + } + } + } + } + + /** Extracts the XML version from the Document. */ + protected String getVersion(Document document) { + if (document == null) { + return null; + } + String version = null; + Method getXMLVersion = null; + try { + getXMLVersion = document.getClass().getMethod("getXmlVersion", //$NON-NLS-1$ + new Class[] {}); + // If Document class implements DOM L3, this method will exist. + if (getXMLVersion != null) { + version = (String) getXMLVersion.invoke(document, + (Object[]) null); + } + } catch (Exception e) { + // Either this locator object doesn't have + // this method, or we're on an old JDK. + } + return version; + } + + protected void writeAnyNode(Node node) throws ShellException { + // is there anything to do? + if (node == null) { + return; + } + + short type = node.getNodeType(); + switch (type) { + case Node.DOCUMENT_NODE: + write((Document) node); + break; + + case Node.DOCUMENT_TYPE_NODE: + write((DocumentType) node); + break; + + case Node.ELEMENT_NODE: + write((Element) node); + break; + + case Node.ENTITY_REFERENCE_NODE: + write((EntityReference) node); + break; + + case Node.CDATA_SECTION_NODE: + write((CDATASection) node); + break; + + case Node.TEXT_NODE: + write((Text) node); + break; + + case Node.PROCESSING_INSTRUCTION_NODE: + write((ProcessingInstruction) node); + break; + + case Node.COMMENT_NODE: + write((Comment) node); + break; + + default: + throw new ShellException(getString( + "RuntimeError.18", Short.toString(type))); //$NON-NLS-1$ + } + } + + protected void write(Document node) throws ShellException { + isXML11 = "1.1".equals(getVersion(node)); //$NON-NLS-1$ + if (isXML11) { + printWriter.println(""); //$NON-NLS-1$ + } else { + printWriter.println(""); //$NON-NLS-1$ + } + printWriter.flush(); + write(node.getDoctype()); + write(node.getDocumentElement()); + } + + protected void write(DocumentType node) throws ShellException { + printWriter.print("'); + } + + protected void write(Element node) throws ShellException { + printWriter.print('<'); + printWriter.print(node.getNodeName()); + Attr attrs[] = sortAttributes(node.getAttributes()); + for (Attr attr : attrs) { + printWriter.print(' '); + printWriter.print(attr.getNodeName()); + printWriter.print("=\""); //$NON-NLS-1$ + normalizeAndPrint(attr.getNodeValue(), true); + printWriter.print('"'); + } + + if (node.getChildNodes().getLength() == 0) { + printWriter.print(" />"); //$NON-NLS-1$ + printWriter.flush(); + } else { + printWriter.print('>'); + printWriter.flush(); + + Node child = node.getFirstChild(); + while (child != null) { + writeAnyNode(child); + child = child.getNextSibling(); + } + + printWriter.print("'); + printWriter.flush(); + } + } + + protected void write(EntityReference node) { + printWriter.print('&'); + printWriter.print(node.getNodeName()); + printWriter.print(';'); + printWriter.flush(); + } + + protected void write(CDATASection node) { + printWriter.print(""); //$NON-NLS-1$ + printWriter.flush(); + } + + protected void write(Text node) { + normalizeAndPrint(node.getNodeValue(), false); + printWriter.flush(); + } + + protected void write(ProcessingInstruction node) { + printWriter.print(" 0) { + printWriter.print(' '); + printWriter.print(data); + } + printWriter.print("?>"); //$NON-NLS-1$ + printWriter.flush(); + } + + protected void write(Comment node) { + printWriter.print(""); //$NON-NLS-1$ + printWriter.flush(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/ExtendedDAOMethodNameCalculator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/ExtendedDAOMethodNameCalculator.java new file mode 100644 index 0000000..dd87884 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/ExtendedDAOMethodNameCalculator.java @@ -0,0 +1,261 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal; + +import org.mybatis.generator.api.DAOMethodNameCalculator; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.internal.rules.Rules; + +/** + * @author Jeff Butler + * + */ +public class ExtendedDAOMethodNameCalculator implements DAOMethodNameCalculator { + + /** + * + */ + public ExtendedDAOMethodNameCalculator() { + super(); + } + + public String getInsertMethodName(IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("insert"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + + return sb.toString(); + } + + /** + * 1. if this will be the only updateByPrimaryKey, then the result should be + * updateByPrimaryKey. 2. If the other method is enabled, but there are + * seperate base and blob classes, then the method name should be + * updateByPrimaryKey 3. Else the method name should be + * updateByPrimaryKeyWithoutBLOBs + */ + public String getUpdateByPrimaryKeyWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByPrimaryKeyWithBLOBs()) { + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + } else { + sb.append("ByPrimaryKeyWithoutBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + /** + * 1. if this will be the only updateByPrimaryKey, then the result should be + * updateByPrimaryKey. 2. If the other method is enabled, but there are + * seperate base and blob classes, then the method name should be + * updateByPrimaryKey 3. Else the method name should be + * updateByPrimaryKeyWithBLOBs + */ + public String getUpdateByPrimaryKeyWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByPrimaryKeyWithoutBLOBs()) { + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + } else { + sb.append("ByPrimaryKeyWithBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + public String getDeleteByExampleMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("delete"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByExample"); //$NON-NLS-1$ + + return sb.toString(); + } + + public String getDeleteByPrimaryKeyMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("delete"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + + return sb.toString(); + } + + /** + * 1. if this will be the only selectByExample, then the result should be + * selectByExample. 2. Else the method name should be + * selectByExampleWithoutBLOBs + */ + public String getSelectByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("select"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByExample"); //$NON-NLS-1$ + + Rules rules = introspectedTable.getRules(); + + if (rules.generateSelectByExampleWithBLOBs()) { + sb.append("WithoutBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + /** + * 1. if this will be the only selectByExample, then the result should be + * selectByExample. 2. Else the method name should be + * selectByExampleWithBLOBs + */ + public String getSelectByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("select"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByExample"); //$NON-NLS-1$ + + Rules rules = introspectedTable.getRules(); + + if (rules.generateSelectByExampleWithoutBLOBs()) { + sb.append("WithBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + public String getSelectByPrimaryKeyMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("select"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByPrimaryKey"); //$NON-NLS-1$ + + return sb.toString(); + } + + public String getUpdateByPrimaryKeySelectiveMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByPrimaryKeySelective"); //$NON-NLS-1$ + + return sb.toString(); + } + + public String getCountByExampleMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("count"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByExample"); //$NON-NLS-1$ + + return sb.toString(); + } + + public String getUpdateByExampleSelectiveMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("ByExampleSelective"); //$NON-NLS-1$ + + return sb.toString(); + } + + public String getUpdateByExampleWithBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByExampleWithoutBLOBs()) { + sb.append("ByExample"); //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + sb.append("ByExample"); //$NON-NLS-1$ + } else { + sb.append("ByExampleWithBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + public String getUpdateByExampleWithoutBLOBsMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + + sb.append("update"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + + Rules rules = introspectedTable.getRules(); + + if (!rules.generateUpdateByExampleWithBLOBs()) { + sb.append("ByExample"); //$NON-NLS-1$ + } else if (rules.generateRecordWithBLOBsClass()) { + sb.append("ByExample"); //$NON-NLS-1$ + } else { + sb.append("ByExampleWithoutBLOBs"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + public String getInsertSelectiveMethodName( + IntrospectedTable introspectedTable) { + StringBuilder sb = new StringBuilder(); + sb.append("insert"); //$NON-NLS-1$ + sb.append(introspectedTable.getFullyQualifiedTable() + .getDomainObjectName()); + sb.append("Selective"); //$NON-NLS-1$ + + return sb.toString(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/NullProgressCallback.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/NullProgressCallback.java new file mode 100644 index 0000000..f5472ca --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/NullProgressCallback.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal; + +import org.mybatis.generator.api.ProgressCallback; + +/** + * This class implements a progress callback that does nothing. It is used when + * the client passes in a null for the ProgressCallback. + * + * @author Jeff Butler + */ +public class NullProgressCallback implements ProgressCallback { + + /** + * + */ + public NullProgressCallback() { + super(); + } + + public void generationStarted(int totalTasks) { + } + + public void introspectionStarted(int totalTasks) { + } + + public void saveStarted(int totalTasks) { + } + + public void startTask(String taskName) { + } + + public void checkCancel() throws InterruptedException { + } + + public void done() { + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/PluginAggregator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/PluginAggregator.java new file mode 100644 index 0000000..a71b3c3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/PluginAggregator.java @@ -0,0 +1,1195 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.mybatis.generator.api.GeneratedJavaFile; +import org.mybatis.generator.api.GeneratedXmlFile; +import org.mybatis.generator.api.Plugin; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.Interface; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.api.dom.xml.Document; +import org.mybatis.generator.api.dom.xml.XmlElement; +import org.mybatis.generator.config.Context; + +/** + * This class is for internal use only. It contains a list of plugins for the + * current context and is used to aggregate plugins together. This class + * implements the rule that if any plugin returns "false" from a method, then no + * other plugin is called. + *

+ * This class does not follow the normal plugin lifecycle and should not be + * subclassed by clients. + * + * @author Jeff Butler + * + */ +public final class PluginAggregator implements Plugin { + private List plugins; + + public PluginAggregator() { + plugins = new ArrayList(); + } + + public void addPlugin(Plugin plugin) { + plugins.add(plugin); + } + + public void setContext(Context context) { + throw new UnsupportedOperationException(); + } + + public void setProperties(Properties properties) { + throw new UnsupportedOperationException(); + } + + public boolean validate(List warnings) { + throw new UnsupportedOperationException(); + } + + public boolean modelBaseRecordClassGenerated(TopLevelClass tlc, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelBaseRecordClassGenerated(tlc, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass tlc, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelRecordWithBLOBsClassGenerated(tlc, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapCountByExampleElementGenerated(XmlElement element, + IntrospectedTable table) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapCountByExampleElementGenerated(element, table)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapDeleteByExampleElementGenerated(XmlElement element, + IntrospectedTable table) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapDeleteByExampleElementGenerated(element, table)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, + IntrospectedTable table) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin + .sqlMapDeleteByPrimaryKeyElementGenerated(element, table)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean modelExampleClassGenerated(TopLevelClass tlc, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelExampleClassGenerated(tlc, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public List contextGenerateAdditionalJavaFiles( + IntrospectedTable introspectedTable) { + List answer = new ArrayList(); + for (Plugin plugin : plugins) { + List temp = plugin + .contextGenerateAdditionalJavaFiles(introspectedTable); + if (temp != null) { + answer.addAll(temp); + } + } + return answer; + } + + public List contextGenerateAdditionalXmlFiles( + IntrospectedTable introspectedTable) { + List answer = new ArrayList(); + for (Plugin plugin : plugins) { + List temp = plugin + .contextGenerateAdditionalXmlFiles(introspectedTable); + if (temp != null) { + answer.addAll(temp); + } + } + return answer; + } + + public boolean modelPrimaryKeyClassGenerated(TopLevelClass tlc, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelPrimaryKeyClassGenerated(tlc, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapResultMapWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapResultMapWithoutBLOBsElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapExampleWhereClauseElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapExampleWhereClauseElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapInsertElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin + .sqlMapInsertElementGenerated(element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapResultMapWithBLOBsElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapResultMapWithBLOBsElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapSelectByExampleWithoutBLOBsElementGenerated( + element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapSelectByExampleWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapSelectByExampleWithBLOBsElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapSelectByPrimaryKeyElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapSelectByPrimaryKeyElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapGenerated(sqlMap, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByExampleSelectiveElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByExampleSelectiveElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByExampleWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByExampleWithBLOBsElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByExampleWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByExampleWithoutBLOBsElementGenerated( + element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByPrimaryKeySelectiveElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByPrimaryKeySelectiveElementGenerated( + element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated( + element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated( + XmlElement element, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated( + element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientCountByExampleMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientCountByExampleMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientCountByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientCountByExampleMethodGenerated(method, topLevelClass, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientDeleteByExampleMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientDeleteByExampleMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientDeleteByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientDeleteByExampleMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientDeleteByPrimaryKeyMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientDeleteByPrimaryKeyMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientInsertMethodGenerated(Method method, Interface interfaze, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientInsertMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientInsertMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientInsertMethodGenerated(method, topLevelClass, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientGenerated(Interface interfaze, + TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientGenerated(interfaze, topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectAllMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectAllMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectAllMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectAllMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByExampleWithBLOBsMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByExampleWithBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByExampleWithoutBLOBsMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByExampleWithoutBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByPrimaryKeyMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientSelectByPrimaryKeyMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleSelectiveMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleSelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleWithBLOBsMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleWithBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleWithoutBLOBsMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByExampleWithoutBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeySelectiveMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeySelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(method, + interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + Method method, Interface interfaze, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + method, interfaze, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated( + method, topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public List contextGenerateAdditionalJavaFiles() { + List answer = new ArrayList(); + for (Plugin plugin : plugins) { + List temp = plugin + .contextGenerateAdditionalJavaFiles(); + if (temp != null) { + answer.addAll(temp); + } + } + return answer; + } + + public List contextGenerateAdditionalXmlFiles() { + List answer = new ArrayList(); + for (Plugin plugin : plugins) { + List temp = plugin + .contextGenerateAdditionalXmlFiles(); + if (temp != null) { + answer.addAll(temp); + } + } + return answer; + } + + public boolean sqlMapDocumentGenerated(Document document, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapDocumentGenerated(document, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean modelFieldGenerated(Field field, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelFieldGenerated(field, topLevelClass, + introspectedColumn, introspectedTable, modelClassType)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean modelGetterMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelGetterMethodGenerated(method, topLevelClass, + introspectedColumn, introspectedTable, modelClassType)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean modelSetterMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, + IntrospectedTable introspectedTable, + Plugin.ModelClassType modelClassType) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.modelSetterMethodGenerated(method, topLevelClass, + introspectedColumn, introspectedTable, modelClassType)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapInsertSelectiveElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapInsertSelectiveElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientInsertSelectiveMethodGenerated(Method method, + Interface interfaze, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientInsertSelectiveMethodGenerated(method, interfaze, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean clientInsertSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.clientInsertSelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public void initialized(IntrospectedTable introspectedTable) { + for (Plugin plugin : plugins) { + plugin.initialized(introspectedTable); + } + } + + public boolean sqlMapBaseColumnListElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapBaseColumnListElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapBlobColumnListElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapBlobColumnListElementGenerated(element, + introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerGenerated(topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerApplyWhereMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerApplyWhereMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerCountByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerCountByExampleMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerDeleteByExampleMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerDeleteByExampleMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerInsertSelectiveMethodGenerated(Method method, + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerInsertSelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerSelectByExampleWithBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerSelectByExampleWithBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerSelectByExampleWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerSelectByExampleWithoutBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerUpdateByExampleSelectiveMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerUpdateByExampleSelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerUpdateByExampleWithBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerUpdateByExampleWithBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerUpdateByExampleWithoutBLOBsMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerUpdateByExampleWithoutBLOBsMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean providerUpdateByPrimaryKeySelectiveMethodGenerated( + Method method, TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.providerUpdateByPrimaryKeySelectiveMethodGenerated(method, + topLevelClass, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } + + public boolean sqlMapSelectAllElementGenerated(XmlElement element, + IntrospectedTable introspectedTable) { + boolean rc = true; + + for (Plugin plugin : plugins) { + if (!plugin.sqlMapSelectAllElementGenerated(element, introspectedTable)) { + rc = false; + break; + } + } + + return rc; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/XmlFileMergerJaxp.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/XmlFileMergerJaxp.java new file mode 100644 index 0000000..b1e8ff3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/XmlFileMergerJaxp.java @@ -0,0 +1,246 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.mybatis.generator.api.GeneratedXmlFile; +import org.mybatis.generator.config.MergeConstants; +import org.mybatis.generator.exception.ShellException; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * This class handles the task of merging changes into an existing XML file. + * + * @author Jeff Butler + */ +public class XmlFileMergerJaxp { + private static class NullEntityResolver implements EntityResolver { + /** + * returns an empty reader. This is done so that the parser doesn't + * attempt to read a DTD. We don't need that support for the merge and + * it can cause problems on systems that aren't Internet connected. + */ + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + + StringReader sr = new StringReader(""); //$NON-NLS-1$ + + return new InputSource(sr); + } + } + + /** + * Utility class - no instances allowed + */ + private XmlFileMergerJaxp() { + super(); + } + + public static String getMergedSource(GeneratedXmlFile generatedXmlFile, + File existingFile) throws ShellException { + + try { + return getMergedSource(new InputSource(new StringReader(generatedXmlFile.getFormattedContent())), + new InputSource(new InputStreamReader(new FileInputStream(existingFile), "UTF-8")), //$NON-NLS-1$ + existingFile.getName()); + } catch (IOException e) { + throw new ShellException(getString("Warning.13", //$NON-NLS-1$ + existingFile.getName()), e); + } catch (SAXException e) { + throw new ShellException(getString("Warning.13", //$NON-NLS-1$ + existingFile.getName()), e); + } catch (ParserConfigurationException e) { + throw new ShellException(getString("Warning.13", //$NON-NLS-1$ + existingFile.getName()), e); + } + } + + public static String getMergedSource(InputSource newFile, + InputSource existingFile, String existingFileName) throws IOException, SAXException, + ParserConfigurationException, ShellException { + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setExpandEntityReferences(false); + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new NullEntityResolver()); + + Document existingDocument = builder.parse(existingFile); + Document newDocument = builder.parse(newFile); + + DocumentType newDocType = newDocument.getDoctype(); + DocumentType existingDocType = existingDocument.getDoctype(); + + if (!newDocType.getName().equals(existingDocType.getName())) { + throw new ShellException(getString("Warning.12", //$NON-NLS-1$ + existingFileName)); + } + + Element existingRootElement = existingDocument.getDocumentElement(); + Element newRootElement = newDocument.getDocumentElement(); + + // reconcile the root element attributes - + // take all attributes from the new element and add to the existing + // element + + // remove all attributes from the existing root element + NamedNodeMap attributes = existingRootElement.getAttributes(); + int attributeCount = attributes.getLength(); + for (int i = attributeCount - 1; i >= 0; i--) { + Node node = attributes.item(i); + existingRootElement.removeAttribute(node.getNodeName()); + } + + // add attributes from the new root node to the old root node + attributes = newRootElement.getAttributes(); + attributeCount = attributes.getLength(); + for (int i = 0; i < attributeCount; i++) { + Node node = attributes.item(i); + existingRootElement.setAttribute(node.getNodeName(), node + .getNodeValue()); + } + + // remove the old generated elements and any + // white space before the old nodes + List nodesToDelete = new ArrayList(); + NodeList children = existingRootElement.getChildNodes(); + int length = children.getLength(); + for (int i = 0; i < length; i++) { + Node node = children.item(i); + if (isGeneratedNode(node)) { + nodesToDelete.add(node); + } else if (isWhiteSpace(node) + && isGeneratedNode(children.item(i + 1))) { + nodesToDelete.add(node); + } + } + + for (Node node : nodesToDelete) { + existingRootElement.removeChild(node); + } + + // add the new generated elements + children = newRootElement.getChildNodes(); + length = children.getLength(); + Node firstChild = existingRootElement.getFirstChild(); + for (int i = 0; i < length; i++) { + Node node = children.item(i); + // don't add the last node if it is only white space + if (i == length - 1) { + if (isWhiteSpace(node)) { + break; + } + } + + Node newNode = existingDocument.importNode(node, true); + if (firstChild == null) { + existingRootElement.appendChild(newNode); + } else { + existingRootElement.insertBefore(newNode, firstChild); + } + } + + // pretty print the result + return prettyPrint(existingDocument); + } + + private static String prettyPrint(Document document) throws ShellException { + DomWriter dw = new DomWriter(); + String s = dw.toString(document); + return s; + } + + private static boolean isGeneratedNode(Node node) { + boolean rc = false; + + if (node != null && node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + String id = element.getAttribute("id"); //$NON-NLS-1$ + if (id != null) { + for (String prefix : MergeConstants.OLD_XML_ELEMENT_PREFIXES) { + if (id.startsWith(prefix)) { + rc = true; + break; + } + } + } + + if (rc == false) { + // check for new node format - if the first non-whitespace node + // is an XML comment, and the comment includes + // one of the old element tags, + // then it is a generated node + NodeList children = node.getChildNodes(); + int length = children.getLength(); + for (int i = 0; i < length; i++) { + Node childNode = children.item(i); + if (isWhiteSpace(childNode)) { + continue; + } else if (childNode.getNodeType() == Node.COMMENT_NODE) { + Comment comment = (Comment) childNode; + String commentData = comment.getData(); + for (String tag : MergeConstants.OLD_ELEMENT_TAGS) { + if (commentData.contains(tag)) { + rc = true; + break; + } + } + } else { + break; + } + } + } + } + + return rc; + } + + private static boolean isWhiteSpace(Node node) { + boolean rc = false; + + if (node != null && node.getNodeType() == Node.TEXT_NODE) { + Text tn = (Text) node; + if (tn.getData().trim().length() == 0) { + rc = true; + } + } + + return rc; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ActualTableName.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ActualTableName.java new file mode 100644 index 0000000..6546887 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ActualTableName.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.db; + +import static org.mybatis.generator.internal.util.StringUtility.composeFullyQualifiedTableName; + +/** + * This class holds the actual catalog, schema, and table name returned from the + * database introspection. + * + * @author Jeff Butler + * + */ +public class ActualTableName { + + private String tableName; + private String catalog; + private String schema; + private String fullName; + + public ActualTableName(String catalog, String schema, String tableName) { + this.catalog = catalog; + this.schema = schema; + this.tableName = tableName; + fullName = composeFullyQualifiedTableName(catalog, + schema, tableName, '.'); + } + + public String getCatalog() { + return catalog; + } + + public String getSchema() { + return schema; + } + + public String getTableName() { + return tableName; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ActualTableName)) { + return false; + } + + return obj.toString().equals(this.toString()); + } + + @Override + public int hashCode() { + return fullName.hashCode(); + } + + @Override + public String toString() { + return fullName; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ConnectionFactory.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ConnectionFactory.java new file mode 100644 index 0000000..1900da1 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/ConnectionFactory.java @@ -0,0 +1,90 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.db; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.SQLException; +import java.util.Properties; + +import org.mybatis.generator.config.JDBCConnectionConfiguration; +import org.mybatis.generator.internal.ObjectFactory; + +/** + * This class assumes that classes are cached elsewhere for performance reasons, + * but also to make sure that any native libraries are only loaded one time + * (avoids the dreaded UnsatisfiedLinkError library loaded in another + * classloader) + * + * @author Jeff Butler + */ +public class ConnectionFactory { + + private static ConnectionFactory instance = new ConnectionFactory(); + + public static ConnectionFactory getInstance() { + return instance; + } + + /** + * + */ + private ConnectionFactory() { + super(); + } + + public Connection getConnection(JDBCConnectionConfiguration config) + throws SQLException { + Driver driver = getDriver(config); + + Properties props = new Properties(); + + if (stringHasValue(config.getUserId())) { + props.setProperty("user", config.getUserId()); //$NON-NLS-1$ + } + + if (stringHasValue(config.getPassword())) { + props.setProperty("password", config.getPassword()); //$NON-NLS-1$ + } + + props.putAll(config.getProperties()); + + Connection conn = driver.connect(config.getConnectionURL(), props); + + if (conn == null) { + throw new SQLException(getString("RuntimeError.7")); //$NON-NLS-1$ + } + + return conn; + } + + private Driver getDriver(JDBCConnectionConfiguration connectionInformation) { + String driverClass = connectionInformation.getDriverClass(); + Driver driver; + + try { + Class clazz = ObjectFactory.externalClassForName(driverClass); + driver = (Driver) clazz.newInstance(); + } catch (Exception e) { + throw new RuntimeException(getString("RuntimeError.8"), e); //$NON-NLS-1$ + } + + return driver; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseDialects.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseDialects.java new file mode 100644 index 0000000..9f2b4e4 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseDialects.java @@ -0,0 +1,79 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.db; + +/** + * Typesafe enum of known database dialects + * + * @author Jeff Butler + */ +public enum DatabaseDialects { + + DB2("VALUES IDENTITY_VAL_LOCAL()"), //$NON-NLS-1$ + MYSQL("SELECT LAST_INSERT_ID()"), //$NON-NLS-1$ + SQLSERVER("SELECT SCOPE_IDENTITY()"), //$NON-NLS-1$ + CLOUDSCAPE("VALUES IDENTITY_VAL_LOCAL()"), //$NON-NLS-1$ + DERBY("VALUES IDENTITY_VAL_LOCAL()"), //$NON-NLS-1$ + HSQLDB("CALL IDENTITY()"), //$NON-NLS-1$ + SYBASE("SELECT @@IDENTITY"), //$NON-NLS-1$ + DB2_MF("SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"), //$NON-NLS-1$ + INFORMIX("select dbinfo('sqlca.sqlerrd1') from systables where tabid=1"); //$NON-NLS-1$ + + private String identityRetrievalStatement; + + /** + * + */ + private DatabaseDialects(String identityRetrievalStatement) { + this.identityRetrievalStatement = identityRetrievalStatement; + } + + public String getIdentityRetrievalStatement() { + return identityRetrievalStatement; + } + + /** + * + * @param database + * @return the database dialect for the selected database. May return null + * if there is no known dialect for the selected db + */ + public static DatabaseDialects getDatabaseDialect(String database) { + DatabaseDialects returnValue = null; + + if ("DB2".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = DB2; + } else if ("MySQL".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = MYSQL; + } else if ("SqlServer".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = SQLSERVER; + } else if ("Cloudscape".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = CLOUDSCAPE; + } else if ("Derby".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = DERBY; + } else if ("HSQLDB".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = HSQLDB; + } else if ("SYBASE".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = SYBASE; + } else if ("DB2_MF".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = DB2_MF; + } else if ("Informix".equalsIgnoreCase(database)) { //$NON-NLS-1$ + returnValue = INFORMIX; + } + + return returnValue; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseIntrospector.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseIntrospector.java new file mode 100644 index 0000000..ea3c4f3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/DatabaseIntrospector.java @@ -0,0 +1,623 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.db; + +import static org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString; +import static org.mybatis.generator.internal.util.JavaBeansUtil.getValidPropertyName; +import static org.mybatis.generator.internal.util.StringUtility.composeFullyQualifiedTableName; +import static org.mybatis.generator.internal.util.StringUtility.isTrue; +import static org.mybatis.generator.internal.util.StringUtility.stringContainsSQLWildcard; +import static org.mybatis.generator.internal.util.StringUtility.stringContainsSpace; +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.mybatis.generator.api.FullyQualifiedTable; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.JavaTypeResolver; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.config.ColumnOverride; +import org.mybatis.generator.config.Context; +import org.mybatis.generator.config.GeneratedKey; +import org.mybatis.generator.config.PropertyRegistry; +import org.mybatis.generator.config.TableConfiguration; +import org.mybatis.generator.internal.ObjectFactory; +import org.mybatis.generator.logging.Log; +import org.mybatis.generator.logging.LogFactory; + +/** + * + * @author Jeff Butler + */ +public class DatabaseIntrospector { + + private DatabaseMetaData databaseMetaData; + private JavaTypeResolver javaTypeResolver; + private List warnings; + private Context context; + private Log logger; + + public DatabaseIntrospector(Context context, + DatabaseMetaData databaseMetaData, + JavaTypeResolver javaTypeResolver, List warnings) { + super(); + this.context = context; + this.databaseMetaData = databaseMetaData; + this.javaTypeResolver = javaTypeResolver; + this.warnings = warnings; + logger = LogFactory.getLog(getClass()); + } + + private void calculatePrimaryKey(FullyQualifiedTable table, + IntrospectedTable introspectedTable) { + ResultSet rs = null; + + try { + rs = databaseMetaData.getPrimaryKeys( + table.getIntrospectedCatalog(), table + .getIntrospectedSchema(), table + .getIntrospectedTableName()); + } catch (SQLException e) { + closeResultSet(rs); + warnings.add(getString("Warning.15")); //$NON-NLS-1$ + return; + } + + try { + // keep primary columns in key sequence order + Map keyColumns = new TreeMap(); + while (rs.next()) { + String columnName = rs.getString("COLUMN_NAME"); //$NON-NLS-1$ + short keySeq = rs.getShort("KEY_SEQ"); //$NON-NLS-1$ + keyColumns.put(keySeq, columnName); + } + + for (String columnName : keyColumns.values()) { + introspectedTable.addPrimaryKeyColumn(columnName); + } + } catch (SQLException e) { + // ignore the primary key if there's any error + } finally { + closeResultSet(rs); + } + } + + private void closeResultSet(ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + // ignore + ; + } + } + } + + private void reportIntrospectionWarnings( + IntrospectedTable introspectedTable, + TableConfiguration tableConfiguration, FullyQualifiedTable table) { + // make sure that every column listed in column overrides + // actually exists in the table + for (ColumnOverride columnOverride : tableConfiguration + .getColumnOverrides()) { + if (introspectedTable.getColumn(columnOverride.getColumnName()) == null) { + warnings.add(getString("Warning.3", //$NON-NLS-1$ + columnOverride.getColumnName(), table.toString())); + } + } + + // make sure that every column listed in ignored columns + // actually exists in the table + for (String string : tableConfiguration.getIgnoredColumnsInError()) { + warnings.add(getString("Warning.4", //$NON-NLS-1$ + string, table.toString())); + } + + GeneratedKey generatedKey = tableConfiguration.getGeneratedKey(); + if (generatedKey != null + && introspectedTable.getColumn(generatedKey.getColumn()) == null) { + if (generatedKey.isIdentity()) { + warnings.add(getString("Warning.5", //$NON-NLS-1$ + generatedKey.getColumn(), table.toString())); + } else { + warnings.add(getString("Warning.6", //$NON-NLS-1$ + generatedKey.getColumn(), table.toString())); + } + } + } + + /** + * Returns a List that matches the specified table + * configuration. + * + * @param tc + * @return a list of introspected tables + * @throws SQLException + */ + public List introspectTables(TableConfiguration tc) + throws SQLException { + + // get the raw columns from the DB + Map> columns = getColumns(tc); + + if (columns.isEmpty()) { + warnings.add(getString("Warning.19", tc.getCatalog(), //$NON-NLS-1$ + tc.getSchema(), tc.getTableName())); + return null; + } + + removeIgnoredColumns(tc, columns); + calculateExtraColumnInformation(tc, columns); + applyColumnOverrides(tc, columns); + calculateIdentityColumns(tc, columns); + + List introspectedTables = calculateIntrospectedTables( + tc, columns); + + // now introspectedTables has all the columns from all the + // tables in the configuration. Do some validation... + + Iterator iter = introspectedTables.iterator(); + while (iter.hasNext()) { + IntrospectedTable introspectedTable = iter.next(); + + if (!introspectedTable.hasAnyColumns()) { + // add warning that the table has no columns, remove from the + // list + String warning = getString( + "Warning.1", introspectedTable.getFullyQualifiedTable().toString()); //$NON-NLS-1$ + warnings.add(warning); + iter.remove(); + } else if (!introspectedTable.hasPrimaryKeyColumns() + && !introspectedTable.hasBaseColumns()) { + // add warning that the table has only BLOB columns, remove from + // the list + String warning = getString( + "Warning.18", introspectedTable.getFullyQualifiedTable().toString()); //$NON-NLS-1$ + warnings.add(warning); + iter.remove(); + } else { + // now make sure that all columns called out in the + // configuration + // actually exist + reportIntrospectionWarnings(introspectedTable, tc, + introspectedTable.getFullyQualifiedTable()); + } + } + + return introspectedTables; + } + + /** + * @param tc + * @param columns + */ + private void removeIgnoredColumns(TableConfiguration tc, + Map> columns) { + for (Map.Entry> entry : columns + .entrySet()) { + Iterator tableColumns = (entry.getValue()) + .iterator(); + while (tableColumns.hasNext()) { + IntrospectedColumn introspectedColumn = tableColumns.next(); + if (tc + .isColumnIgnored(introspectedColumn + .getActualColumnName())) { + tableColumns.remove(); + if (logger.isDebugEnabled()) { + logger.debug(getString("Tracing.3", //$NON-NLS-1$ + introspectedColumn.getActualColumnName(), entry + .getKey().toString())); + } + } + } + } + } + + private void calculateExtraColumnInformation(TableConfiguration tc, + Map> columns) { + StringBuilder sb = new StringBuilder(); + Pattern pattern = null; + String replaceString = null; + if (tc.getColumnRenamingRule() != null) { + pattern = Pattern.compile(tc.getColumnRenamingRule() + .getSearchString()); + replaceString = tc.getColumnRenamingRule().getReplaceString(); + replaceString = replaceString == null ? "" : replaceString; //$NON-NLS-1$ + } + + for (Map.Entry> entry : columns + .entrySet()) { + for (IntrospectedColumn introspectedColumn : entry.getValue()) { + String calculatedColumnName; + if (pattern == null) { + calculatedColumnName = introspectedColumn + .getActualColumnName(); + } else { + Matcher matcher = pattern.matcher(introspectedColumn + .getActualColumnName()); + calculatedColumnName = matcher.replaceAll(replaceString); + } + + if (isTrue(tc + .getProperty(PropertyRegistry.TABLE_USE_ACTUAL_COLUMN_NAMES))) { + introspectedColumn.setJavaProperty( + getValidPropertyName(calculatedColumnName)); + } else if (isTrue(tc + .getProperty(PropertyRegistry.TABLE_USE_COMPOUND_PROPERTY_NAMES))) { + sb.setLength(0); + sb.append(calculatedColumnName); + sb.append('_'); + sb.append(getCamelCaseString( + introspectedColumn.getRemarks(), true)); + introspectedColumn.setJavaProperty( + getValidPropertyName(sb.toString())); + } else { + introspectedColumn.setJavaProperty( + getCamelCaseString(calculatedColumnName, false)); + } + + FullyQualifiedJavaType fullyQualifiedJavaType = javaTypeResolver + .calculateJavaType(introspectedColumn); + + if (fullyQualifiedJavaType != null) { + introspectedColumn + .setFullyQualifiedJavaType(fullyQualifiedJavaType); + introspectedColumn.setJdbcTypeName(javaTypeResolver + .calculateJdbcTypeName(introspectedColumn)); + } else { + // type cannot be resolved. Check for ignored or overridden + boolean warn = true; + if (tc.isColumnIgnored(introspectedColumn + .getActualColumnName())) { + warn = false; + } + + ColumnOverride co = tc.getColumnOverride(introspectedColumn + .getActualColumnName()); + if (co != null) { + if (stringHasValue(co.getJavaType()) + && stringHasValue(co.getJavaType())) { + warn = false; + } + } + + // if the type is not supported, then we'll report a warning + if (warn) { + introspectedColumn + .setFullyQualifiedJavaType(FullyQualifiedJavaType + .getObjectInstance()); + introspectedColumn.setJdbcTypeName("OTHER"); //$NON-NLS-1$ + + String warning = getString("Warning.14", //$NON-NLS-1$ + Integer.toString(introspectedColumn.getJdbcType()), + entry.getKey().toString(), + introspectedColumn.getActualColumnName()); + + warnings.add(warning); + } + } + + if (context.autoDelimitKeywords()) { + if (SqlReservedWords.containsWord(introspectedColumn + .getActualColumnName())) { + introspectedColumn.setColumnNameDelimited(true); + } + } + + if (tc.isAllColumnDelimitingEnabled()) { + introspectedColumn.setColumnNameDelimited(true); + } + } + } + } + + private void calculateIdentityColumns(TableConfiguration tc, + Map> columns) { + GeneratedKey gk = tc.getGeneratedKey(); + if (gk == null) { + // no generated key, then no identity or sequence columns + return; + } + + for (Map.Entry> entry : columns + .entrySet()) { + for (IntrospectedColumn introspectedColumn : entry.getValue()) { + if (isMatchedColumn(introspectedColumn, gk)) { + if (gk.isIdentity() || gk.isJdbcStandard()) { + introspectedColumn.setIdentity(true); + introspectedColumn.setSequenceColumn(false); + } else { + introspectedColumn.setIdentity(false); + introspectedColumn.setSequenceColumn(true); + } + } + } + } + } + + private boolean isMatchedColumn(IntrospectedColumn introspectedColumn, GeneratedKey gk) { + if (introspectedColumn.isColumnNameDelimited()) { + return introspectedColumn.getActualColumnName().equals(gk.getColumn()); + } else { + return introspectedColumn.getActualColumnName().equalsIgnoreCase(gk.getColumn()); + } + } + + private void applyColumnOverrides(TableConfiguration tc, + Map> columns) { + for (Map.Entry> entry : columns + .entrySet()) { + for (IntrospectedColumn introspectedColumn : entry.getValue()) { + ColumnOverride columnOverride = tc + .getColumnOverride(introspectedColumn + .getActualColumnName()); + + if (columnOverride != null) { + if (logger.isDebugEnabled()) { + logger.debug(getString("Tracing.4", //$NON-NLS-1$ + introspectedColumn.getActualColumnName(), entry + .getKey().toString())); + } + + if (stringHasValue(columnOverride + .getJavaProperty())) { + introspectedColumn.setJavaProperty(columnOverride + .getJavaProperty()); + } + + if (stringHasValue(columnOverride + .getJavaType())) { + introspectedColumn + .setFullyQualifiedJavaType(new FullyQualifiedJavaType( + columnOverride.getJavaType())); + } + + if (stringHasValue(columnOverride + .getJdbcType())) { + introspectedColumn.setJdbcTypeName(columnOverride + .getJdbcType()); + } + + if (stringHasValue(columnOverride + .getTypeHandler())) { + introspectedColumn.setTypeHandler(columnOverride + .getTypeHandler()); + } + + if (columnOverride.isColumnNameDelimited()) { + introspectedColumn.setColumnNameDelimited(true); + } + + introspectedColumn.setProperties(columnOverride + .getProperties()); + } + } + } + } + + /** + * This method returns a Map> of + * columns returned from the database introspection. + * + * @param tc + * @return introspected columns + * @throws SQLException + */ + private Map> getColumns( + TableConfiguration tc) throws SQLException { + String localCatalog; + String localSchema; + String localTableName; + + boolean delimitIdentifiers = tc.isDelimitIdentifiers() + || stringContainsSpace(tc.getCatalog()) + || stringContainsSpace(tc.getSchema()) + || stringContainsSpace(tc.getTableName()); + + if (delimitIdentifiers) { + localCatalog = tc.getCatalog(); + localSchema = tc.getSchema(); + localTableName = tc.getTableName(); + } else if (databaseMetaData.storesLowerCaseIdentifiers()) { + localCatalog = tc.getCatalog() == null ? null : tc.getCatalog() + .toLowerCase(); + localSchema = tc.getSchema() == null ? null : tc.getSchema() + .toLowerCase(); + localTableName = tc.getTableName() == null ? null : tc + .getTableName().toLowerCase(); + } else if (databaseMetaData.storesUpperCaseIdentifiers()) { + localCatalog = tc.getCatalog() == null ? null : tc.getCatalog() + .toUpperCase(); + localSchema = tc.getSchema() == null ? null : tc.getSchema() + .toUpperCase(); + localTableName = tc.getTableName() == null ? null : tc + .getTableName().toUpperCase(); + } else { + localCatalog = tc.getCatalog(); + localSchema = tc.getSchema(); + localTableName = tc.getTableName(); + } + + if (tc.isWildcardEscapingEnabled()) { + String escapeString = databaseMetaData.getSearchStringEscape(); + + StringBuilder sb = new StringBuilder(); + StringTokenizer st; + if (localSchema != null) { + st = new StringTokenizer(localSchema, "_%", true); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.equals("_") //$NON-NLS-1$ + || token.equals("%")) { //$NON-NLS-1$ + sb.append(escapeString); + } + sb.append(token); + } + localSchema = sb.toString(); + } + + sb.setLength(0); + st = new StringTokenizer(localTableName, "_%", true); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.equals("_") //$NON-NLS-1$ + || token.equals("%")) { //$NON-NLS-1$ + sb.append(escapeString); + } + sb.append(token); + } + localTableName = sb.toString(); + } + + Map> answer = new HashMap>(); + + if (logger.isDebugEnabled()) { + String fullTableName = composeFullyQualifiedTableName(localCatalog, localSchema, + localTableName, '.'); + logger.debug(getString("Tracing.1", fullTableName)); //$NON-NLS-1$ + } + + ResultSet rs = databaseMetaData.getColumns(localCatalog, localSchema, + localTableName, null); + + while (rs.next()) { + IntrospectedColumn introspectedColumn = ObjectFactory + .createIntrospectedColumn(context); + + introspectedColumn.setTableAlias(tc.getAlias()); + introspectedColumn.setJdbcType(rs.getInt("DATA_TYPE")); //$NON-NLS-1$ + introspectedColumn.setLength(rs.getInt("COLUMN_SIZE")); //$NON-NLS-1$ + introspectedColumn.setActualColumnName(rs.getString("COLUMN_NAME")); //$NON-NLS-1$ + introspectedColumn + .setNullable(rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable); //$NON-NLS-1$ + introspectedColumn.setScale(rs.getInt("DECIMAL_DIGITS")); //$NON-NLS-1$ + introspectedColumn.setRemarks(rs.getString("REMARKS")); //$NON-NLS-1$ + introspectedColumn.setDefaultValue(rs.getString("COLUMN_DEF")); //$NON-NLS-1$ + + ActualTableName atn = new ActualTableName( + rs.getString("TABLE_CAT"), //$NON-NLS-1$ + rs.getString("TABLE_SCHEM"), //$NON-NLS-1$ + rs.getString("TABLE_NAME")); //$NON-NLS-1$ + + List columns = answer.get(atn); + if (columns == null) { + columns = new ArrayList(); + answer.put(atn, columns); + } + + columns.add(introspectedColumn); + + if (logger.isDebugEnabled()) { + logger.debug(getString( + "Tracing.2", //$NON-NLS-1$ + introspectedColumn.getActualColumnName(), Integer + .toString(introspectedColumn.getJdbcType()), + atn.toString())); + } + } + + closeResultSet(rs); + + if (answer.size() > 1 + && !stringContainsSQLWildcard(localSchema) + && !stringContainsSQLWildcard(localTableName)) { + // issue a warning if there is more than one table and + // no wildcards were used + ActualTableName inputAtn = new ActualTableName(tc.getCatalog(), tc + .getSchema(), tc.getTableName()); + + StringBuilder sb = new StringBuilder(); + boolean comma = false; + for (ActualTableName atn : answer.keySet()) { + if (comma) { + sb.append(','); + } else { + comma = true; + } + sb.append(atn.toString()); + } + + warnings.add(getString("Warning.25", //$NON-NLS-1$ + inputAtn.toString(), sb.toString())); + } + + return answer; + } + + private List calculateIntrospectedTables( + TableConfiguration tc, + Map> columns) { + boolean delimitIdentifiers = tc.isDelimitIdentifiers() + || stringContainsSpace(tc.getCatalog()) + || stringContainsSpace(tc.getSchema()) + || stringContainsSpace(tc.getTableName()); + + List answer = new ArrayList(); + + for (Map.Entry> entry : columns + .entrySet()) { + ActualTableName atn = entry.getKey(); + + // we only use the returned catalog and schema if something was + // actually + // specified on the table configuration. If something was returned + // from the DB for these fields, but nothing was specified on the + // table + // configuration, then some sort of DB default is being returned + // and we don't want that in our SQL + FullyQualifiedTable table = new FullyQualifiedTable( + stringHasValue(tc.getCatalog()) ? atn + .getCatalog() : null, + stringHasValue(tc.getSchema()) ? atn + .getSchema() : null, + atn.getTableName(), + tc.getDomainObjectName(), + tc.getAlias(), + isTrue(tc.getProperty(PropertyRegistry.TABLE_IGNORE_QUALIFIERS_AT_RUNTIME)), + tc.getProperty(PropertyRegistry.TABLE_RUNTIME_CATALOG), + tc.getProperty(PropertyRegistry.TABLE_RUNTIME_SCHEMA), + tc.getProperty(PropertyRegistry.TABLE_RUNTIME_TABLE_NAME), + delimitIdentifiers, context); + + IntrospectedTable introspectedTable = ObjectFactory + .createIntrospectedTable(tc, table, context); + + for (IntrospectedColumn introspectedColumn : entry.getValue()) { + introspectedTable.addColumn(introspectedColumn); + } + + calculatePrimaryKey(table, introspectedTable); + + answer.add(introspectedTable); + } + + return answer; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/SqlReservedWords.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/SqlReservedWords.java new file mode 100644 index 0000000..06a0738 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/db/SqlReservedWords.java @@ -0,0 +1,978 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.db; + +import java.util.HashSet; +import java.util.Set; + +/** + * This class contains a somewhat comprehensive list of SQL reserved words. + * Since different databases have different reserved words, this list is + * inclusive of many different databases - so it may include words that are not + * reserved in some databases. + * + * This list is based on the list from Drupal Handbook: + * http://drupal.org/node/141051 With additions for DB2 + * + * @author Jeff Butler + * + */ +public class SqlReservedWords { + + private static Set RESERVED_WORDS; + + static { + String[] words = { "A", //$NON-NLS-1$ + "ABORT", //$NON-NLS-1$ + "ABS", //$NON-NLS-1$ + "ABSOLUTE", //$NON-NLS-1$ + "ACCESS", //$NON-NLS-1$ + "ACTION", //$NON-NLS-1$ + "ADA", //$NON-NLS-1$ + "ADD", // DB2 //$NON-NLS-1$ + "ADMIN", //$NON-NLS-1$ + "AFTER", // DB2 //$NON-NLS-1$ + "AGGREGATE", //$NON-NLS-1$ + "ALIAS", // DB2 //$NON-NLS-1$ + "ALL", // DB2 //$NON-NLS-1$ + "ALLOCATE", // DB2 //$NON-NLS-1$ + "ALLOW", // DB2 //$NON-NLS-1$ + "ALSO", //$NON-NLS-1$ + "ALTER", // DB2 //$NON-NLS-1$ + "ALWAYS", //$NON-NLS-1$ + "ANALYSE", //$NON-NLS-1$ + "ANALYZE", //$NON-NLS-1$ + "AND", // DB2 //$NON-NLS-1$ + "ANY", // DB2 //$NON-NLS-1$ + "APPLICATION", // DB2 //$NON-NLS-1$ + "ARE", //$NON-NLS-1$ + "ARRAY", //$NON-NLS-1$ + "AS", // DB2 //$NON-NLS-1$ + "ASC", //$NON-NLS-1$ + "ASENSITIVE", //$NON-NLS-1$ + "ASSERTION", //$NON-NLS-1$ + "ASSIGNMENT", //$NON-NLS-1$ + "ASSOCIATE", // DB2 //$NON-NLS-1$ + "ASUTIME", // DB2 //$NON-NLS-1$ + "ASYMMETRIC", //$NON-NLS-1$ + "AT", //$NON-NLS-1$ + "ATOMIC", //$NON-NLS-1$ + "ATTRIBUTE", //$NON-NLS-1$ + "ATTRIBUTES", //$NON-NLS-1$ + "AUDIT", // DB2 //$NON-NLS-1$ + "AUTHORIZATION", // DB2 //$NON-NLS-1$ + "AUTO_INCREMENT", //$NON-NLS-1$ + "AUX", // DB2 //$NON-NLS-1$ + "AUXILIARY", // DB2 //$NON-NLS-1$ + "AVG", //$NON-NLS-1$ + "AVG_ROW_LENGTH", //$NON-NLS-1$ + "BACKUP", //$NON-NLS-1$ + "BACKWARD", //$NON-NLS-1$ + "BEFORE", // DB2 //$NON-NLS-1$ + "BEGIN", // DB2 //$NON-NLS-1$ + "BERNOULLI", //$NON-NLS-1$ + "BETWEEN", // DB2 //$NON-NLS-1$ + "BIGINT", //$NON-NLS-1$ + "BINARY", // DB2 //$NON-NLS-1$ + "BIT", //$NON-NLS-1$ + "BIT_LENGTH", //$NON-NLS-1$ + "BITVAR", //$NON-NLS-1$ + "BLOB", //$NON-NLS-1$ + "BOOL", //$NON-NLS-1$ + "BOOLEAN", //$NON-NLS-1$ + "BOTH", //$NON-NLS-1$ + "BREADTH", //$NON-NLS-1$ + "BREAK", //$NON-NLS-1$ + "BROWSE", //$NON-NLS-1$ + "BUFFERPOOL", // DB2 //$NON-NLS-1$ + "BULK", //$NON-NLS-1$ + "BY", // DB2 //$NON-NLS-1$ + "C", //$NON-NLS-1$ + "CACHE", // DB2 //$NON-NLS-1$ + "CALL", // DB2 //$NON-NLS-1$ + "CALLED", // DB2 //$NON-NLS-1$ + "CAPTURE", // DB2 //$NON-NLS-1$ + "CARDINALITY", // DB2 //$NON-NLS-1$ + "CASCADE", //$NON-NLS-1$ + "CASCADED", // DB2 //$NON-NLS-1$ + "CASE", // DB2 //$NON-NLS-1$ + "CAST", // DB2 //$NON-NLS-1$ + "CATALOG", //$NON-NLS-1$ + "CATALOG_NAME", //$NON-NLS-1$ + "CCSID", // DB2 //$NON-NLS-1$ + "CEIL", //$NON-NLS-1$ + "CEILING", //$NON-NLS-1$ + "CHAIN", //$NON-NLS-1$ + "CHANGE", //$NON-NLS-1$ + "CHAR", // DB2 //$NON-NLS-1$ + "CHAR_LENGTH", //$NON-NLS-1$ + "CHARACTER", // DB2 //$NON-NLS-1$ + "CHARACTER_LENGTH", //$NON-NLS-1$ + "CHARACTER_SET_CATALOG", //$NON-NLS-1$ + "CHARACTER_SET_NAME", //$NON-NLS-1$ + "CHARACTER_SET_SCHEMA", //$NON-NLS-1$ + "CHARACTERISTICS", //$NON-NLS-1$ + "CHARACTERS", //$NON-NLS-1$ + "CHECK", // DB2 //$NON-NLS-1$ + "CHECKED", //$NON-NLS-1$ + "CHECKPOINT", //$NON-NLS-1$ + "CHECKSUM", //$NON-NLS-1$ + "CLASS", //$NON-NLS-1$ + "CLASS_ORIGIN", //$NON-NLS-1$ + "CLOB", //$NON-NLS-1$ + "CLOSE", // DB2 //$NON-NLS-1$ + "CLUSTER", // DB2 //$NON-NLS-1$ + "CLUSTERED", //$NON-NLS-1$ + "COALESCE", //$NON-NLS-1$ + "COBOL", //$NON-NLS-1$ + "COLLATE", //$NON-NLS-1$ + "COLLATION", //$NON-NLS-1$ + "COLLATION_CATALOG", //$NON-NLS-1$ + "COLLATION_NAME", //$NON-NLS-1$ + "COLLATION_SCHEMA", //$NON-NLS-1$ + "COLLECT", //$NON-NLS-1$ + "COLLECTION", // DB2 //$NON-NLS-1$ + "COLLID", // DB2 //$NON-NLS-1$ + "COLUMN", // DB2 //$NON-NLS-1$ + "COLUMN_NAME", //$NON-NLS-1$ + "COLUMNS", //$NON-NLS-1$ + "COMMAND_FUNCTION", //$NON-NLS-1$ + "COMMAND_FUNCTION_CODE", //$NON-NLS-1$ + "COMMENT", // DB2 //$NON-NLS-1$ + "COMMIT", // DB2 //$NON-NLS-1$ + "COMMITTED", //$NON-NLS-1$ + "COMPLETION", //$NON-NLS-1$ + "COMPRESS", //$NON-NLS-1$ + "COMPUTE", //$NON-NLS-1$ + "CONCAT", // DB2 //$NON-NLS-1$ + "CONDITION", // DB2 //$NON-NLS-1$ + "CONDITION_NUMBER", //$NON-NLS-1$ + "CONNECT", // DB2 //$NON-NLS-1$ + "CONNECTION", // DB2 //$NON-NLS-1$ + "CONNECTION_NAME", //$NON-NLS-1$ + "CONSTRAINT", // DB2 //$NON-NLS-1$ + "CONSTRAINT_CATALOG", //$NON-NLS-1$ + "CONSTRAINT_NAME", //$NON-NLS-1$ + "CONSTRAINT_SCHEMA", //$NON-NLS-1$ + "CONSTRAINTS", //$NON-NLS-1$ + "CONSTRUCTOR", //$NON-NLS-1$ + "CONTAINS", // DB2 //$NON-NLS-1$ + "CONTAINSTABLE", //$NON-NLS-1$ + "CONTINUE", // DB2 //$NON-NLS-1$ + "CONVERSION", //$NON-NLS-1$ + "CONVERT", //$NON-NLS-1$ + "COPY", //$NON-NLS-1$ + "CORR", //$NON-NLS-1$ + "CORRESPONDING", //$NON-NLS-1$ + "COUNT", // DB2 //$NON-NLS-1$ + "COUNT_BIG", // DB2 //$NON-NLS-1$ + "COVAR_POP", //$NON-NLS-1$ + "COVAR_SAMP", //$NON-NLS-1$ + "CREATE", // DB2 //$NON-NLS-1$ + "CREATEDB", //$NON-NLS-1$ + "CREATEROLE", //$NON-NLS-1$ + "CREATEUSER", //$NON-NLS-1$ + "CROSS", // DB2 //$NON-NLS-1$ + "CSV", //$NON-NLS-1$ + "CUBE", //$NON-NLS-1$ + "CUME_DIST", //$NON-NLS-1$ + "CURRENT", // DB2 //$NON-NLS-1$ + "CURRENT_DATE", // DB2 //$NON-NLS-1$ + "CURRENT_DEFAULT_TRANSFORM_GROUP", //$NON-NLS-1$ + "CURRENT_LC_CTYPE", // DB2 //$NON-NLS-1$ + "CURRENT_PATH", // DB2 //$NON-NLS-1$ + "CURRENT_ROLE", //$NON-NLS-1$ + "CURRENT_SERVER", // DB2 //$NON-NLS-1$ + "CURRENT_TIME", // DB2 //$NON-NLS-1$ + "CURRENT_TIMESTAMP", // DB2 //$NON-NLS-1$ + "CURRENT_TIMEZONE", // DB2 //$NON-NLS-1$ + "CURRENT_TRANSFORM_GROUP_FOR_TYPE", //$NON-NLS-1$ + "CURRENT_USER", // DB2 //$NON-NLS-1$ + "CURSOR", // DB2 //$NON-NLS-1$ + "CURSOR_NAME", //$NON-NLS-1$ + "CYCLE", // DB2 //$NON-NLS-1$ + "DATA", // DB2 //$NON-NLS-1$ + "DATABASE", // DB2 //$NON-NLS-1$ + "DATABASES", //$NON-NLS-1$ + "DATE", //$NON-NLS-1$ + "DATETIME", //$NON-NLS-1$ + "DATETIME_INTERVAL_CODE", //$NON-NLS-1$ + "DATETIME_INTERVAL_PRECISION", //$NON-NLS-1$ + "DAY", // DB2 //$NON-NLS-1$ + "DAY_HOUR", //$NON-NLS-1$ + "DAY_MICROSECOND", //$NON-NLS-1$ + "DAY_MINUTE", //$NON-NLS-1$ + "DAY_SECOND", //$NON-NLS-1$ + "DAYOFMONTH", //$NON-NLS-1$ + "DAYOFWEEK", //$NON-NLS-1$ + "DAYOFYEAR", //$NON-NLS-1$ + "DAYS", // DB2 //$NON-NLS-1$ + "DB2GENERAL", // DB2 //$NON-NLS-1$ + "DB2GNRL", // DB2 //$NON-NLS-1$ + "DB2SQL", // DB2 //$NON-NLS-1$ + "DBCC", //$NON-NLS-1$ + "DBINFO", // DB2 //$NON-NLS-1$ + "DEALLOCATE", //$NON-NLS-1$ + "DEC", //$NON-NLS-1$ + "DECIMAL", //$NON-NLS-1$ + "DECLARE", // DB2 //$NON-NLS-1$ + "DEFAULT", // DB2 //$NON-NLS-1$ + "DEFAULTS", // DB2 //$NON-NLS-1$ + "DEFERRABLE", //$NON-NLS-1$ + "DEFERRED", //$NON-NLS-1$ + "DEFINED", //$NON-NLS-1$ + "DEFINER", //$NON-NLS-1$ + "DEFINITION", // DB2 //$NON-NLS-1$ + "DEGREE", //$NON-NLS-1$ + "DELAY_KEY_WRITE", //$NON-NLS-1$ + "DELAYED", //$NON-NLS-1$ + "DELETE", // DB2 //$NON-NLS-1$ + "DELIMITER", //$NON-NLS-1$ + "DELIMITERS", //$NON-NLS-1$ + "DENSE_RANK", //$NON-NLS-1$ + "DENY", //$NON-NLS-1$ + "DEPTH", //$NON-NLS-1$ + "DEREF", //$NON-NLS-1$ + "DERIVED", //$NON-NLS-1$ + "DESC", //$NON-NLS-1$ + "DESCRIBE", //$NON-NLS-1$ + "DESCRIPTOR", // DB2 //$NON-NLS-1$ + "DESTROY", //$NON-NLS-1$ + "DESTRUCTOR", //$NON-NLS-1$ + "DETERMINISTIC", // DB2 //$NON-NLS-1$ + "DIAGNOSTICS", //$NON-NLS-1$ + "DICTIONARY", //$NON-NLS-1$ + "DISABLE", //$NON-NLS-1$ + "DISALLOW", // DB2 //$NON-NLS-1$ + "DISCONNECT", // DB2 //$NON-NLS-1$ + "DISK", //$NON-NLS-1$ + "DISPATCH", //$NON-NLS-1$ + "DISTINCT", // DB2 //$NON-NLS-1$ + "DISTINCTROW", //$NON-NLS-1$ + "DISTRIBUTED", //$NON-NLS-1$ + "DIV", //$NON-NLS-1$ + "DO", // DB2 //$NON-NLS-1$ + "DOMAIN", //$NON-NLS-1$ + "DOUBLE", // DB2 //$NON-NLS-1$ + "DROP", // DB2 //$NON-NLS-1$ + "DSNHATTR", // DB2 //$NON-NLS-1$ + "DSSIZE", // DB2 //$NON-NLS-1$ + "DUAL", //$NON-NLS-1$ + "DUMMY", //$NON-NLS-1$ + "DUMP", //$NON-NLS-1$ + "DYNAMIC", // DB2 //$NON-NLS-1$ + "DYNAMIC_FUNCTION", //$NON-NLS-1$ + "DYNAMIC_FUNCTION_CODE", //$NON-NLS-1$ + "EACH", // DB2 //$NON-NLS-1$ + "EDITPROC", // DB2 //$NON-NLS-1$ + "ELEMENT", //$NON-NLS-1$ + "ELSE", // DB2 //$NON-NLS-1$ + "ELSEIF", // DB2 //$NON-NLS-1$ + "ENABLE", //$NON-NLS-1$ + "ENCLOSED", //$NON-NLS-1$ + "ENCODING", // DB2 //$NON-NLS-1$ + "ENCRYPTED", //$NON-NLS-1$ + "END", // DB2 //$NON-NLS-1$ + "END-EXEC", // DB2 //$NON-NLS-1$ + "END-EXEC1", // DB2 //$NON-NLS-1$ + "ENUM", //$NON-NLS-1$ + "EQUALS", //$NON-NLS-1$ + "ERASE", // DB2 //$NON-NLS-1$ + "ERRLVL", //$NON-NLS-1$ + "ESCAPE", // DB2 //$NON-NLS-1$ + "ESCAPED", //$NON-NLS-1$ + "EVERY", //$NON-NLS-1$ + "EXCEPT", // DB2 //$NON-NLS-1$ + "EXCEPTION", // DB2 //$NON-NLS-1$ + "EXCLUDE", //$NON-NLS-1$ + "EXCLUDING", // DB2 //$NON-NLS-1$ + "EXCLUSIVE", //$NON-NLS-1$ + "EXEC", //$NON-NLS-1$ + "EXECUTE", // DB2 //$NON-NLS-1$ + "EXISTING", //$NON-NLS-1$ + "EXISTS", // DB2 //$NON-NLS-1$ + "EXIT", // DB2 //$NON-NLS-1$ + "EXP", //$NON-NLS-1$ + "EXPLAIN", //$NON-NLS-1$ + "EXTERNAL", // DB2 //$NON-NLS-1$ + "EXTRACT", //$NON-NLS-1$ + "FALSE", //$NON-NLS-1$ + "FENCED", // DB2 //$NON-NLS-1$ + "FETCH", // DB2 //$NON-NLS-1$ + "FIELDPROC", // DB2 //$NON-NLS-1$ + "FIELDS", //$NON-NLS-1$ + "FILE", // DB2 //$NON-NLS-1$ + "FILLFACTOR", //$NON-NLS-1$ + "FILTER", //$NON-NLS-1$ + "FINAL", // DB2 //$NON-NLS-1$ + "FIRST", //$NON-NLS-1$ + "FLOAT", //$NON-NLS-1$ + "FLOAT4", //$NON-NLS-1$ + "FLOAT8", //$NON-NLS-1$ + "FLOOR", //$NON-NLS-1$ + "FLUSH", //$NON-NLS-1$ + "FOLLOWING", //$NON-NLS-1$ + "FOR", // DB2 //$NON-NLS-1$ + "FORCE", //$NON-NLS-1$ + "FOREIGN", // DB2 //$NON-NLS-1$ + "FORTRAN", //$NON-NLS-1$ + "FORWARD", //$NON-NLS-1$ + "FOUND", //$NON-NLS-1$ + "FREE", // DB2 //$NON-NLS-1$ + "FREETEXT", //$NON-NLS-1$ + "FREETEXTTABLE", //$NON-NLS-1$ + "FREEZE", //$NON-NLS-1$ + "FROM", // DB2 //$NON-NLS-1$ + "FULL", // DB2 //$NON-NLS-1$ + "FULLTEXT", //$NON-NLS-1$ + "FUNCTION", // DB2 //$NON-NLS-1$ + "FUSION", //$NON-NLS-1$ + "G", //$NON-NLS-1$ + "GENERAL", // DB2 //$NON-NLS-1$ + "GENERATED", // DB2 //$NON-NLS-1$ + "GET", // DB2 //$NON-NLS-1$ + "GLOBAL", // DB2 //$NON-NLS-1$ + "GO", // DB2 //$NON-NLS-1$ + "GOTO", // DB2 //$NON-NLS-1$ + "GRANT", // DB2 //$NON-NLS-1$ + "GRANTED", //$NON-NLS-1$ + "GRANTS", //$NON-NLS-1$ + "GRAPHIC", // DB2 //$NON-NLS-1$ + "GREATEST", //$NON-NLS-1$ + "GROUP", // DB2 //$NON-NLS-1$ + "GROUPING", //$NON-NLS-1$ + "HANDLER", // DB2 //$NON-NLS-1$ + "HAVING", // DB2 //$NON-NLS-1$ + "HEADER", //$NON-NLS-1$ + "HEAP", //$NON-NLS-1$ + "HIERARCHY", //$NON-NLS-1$ + "HIGH_PRIORITY", //$NON-NLS-1$ + "HOLD", // DB2 //$NON-NLS-1$ + "HOLDLOCK", //$NON-NLS-1$ + "HOST", //$NON-NLS-1$ + "HOSTS", //$NON-NLS-1$ + "HOUR", // DB2 //$NON-NLS-1$ + "HOUR_MICROSECOND", //$NON-NLS-1$ + "HOUR_MINUTE", //$NON-NLS-1$ + "HOUR_SECOND", //$NON-NLS-1$ + "HOURS", // DB2 //$NON-NLS-1$ + "IDENTIFIED", //$NON-NLS-1$ + "IDENTITY", // DB2 //$NON-NLS-1$ + "IDENTITY_INSERT", //$NON-NLS-1$ + "IDENTITYCOL", //$NON-NLS-1$ + "IF", // DB2 //$NON-NLS-1$ + "IGNORE", //$NON-NLS-1$ + "ILIKE", //$NON-NLS-1$ + "IMMEDIATE", // DB2 //$NON-NLS-1$ + "IMMUTABLE", //$NON-NLS-1$ + "IMPLEMENTATION", //$NON-NLS-1$ + "IMPLICIT", //$NON-NLS-1$ + "IN", // DB2 //$NON-NLS-1$ + "INCLUDE", //$NON-NLS-1$ + "INCLUDING", // DB2 //$NON-NLS-1$ + "INCREMENT", // DB2 //$NON-NLS-1$ + "INDEX", // DB2 //$NON-NLS-1$ + "INDICATOR", // DB2 //$NON-NLS-1$ + "INFILE", //$NON-NLS-1$ + "INFIX", //$NON-NLS-1$ + "INHERIT", // DB2 //$NON-NLS-1$ + "INHERITS", //$NON-NLS-1$ + "INITIAL", //$NON-NLS-1$ + "INITIALIZE", //$NON-NLS-1$ + "INITIALLY", //$NON-NLS-1$ + "INNER", // DB2 //$NON-NLS-1$ + "INOUT", // DB2 //$NON-NLS-1$ + "INPUT", //$NON-NLS-1$ + "INSENSITIVE", // DB2 //$NON-NLS-1$ + "INSERT", // DB2 //$NON-NLS-1$ + "INSERT_ID", //$NON-NLS-1$ + "INSTANCE", //$NON-NLS-1$ + "INSTANTIABLE", //$NON-NLS-1$ + "INSTEAD", //$NON-NLS-1$ + "INT", //$NON-NLS-1$ + "INT1", //$NON-NLS-1$ + "INT2", //$NON-NLS-1$ + "INT3", //$NON-NLS-1$ + "INT4", //$NON-NLS-1$ + "INT8", //$NON-NLS-1$ + "INTEGER", //$NON-NLS-1$ + "INTEGRITY", // DB2 //$NON-NLS-1$ + "INTERSECT", //$NON-NLS-1$ + "INTERSECTION", //$NON-NLS-1$ + "INTERVAL", //$NON-NLS-1$ + "INTO", // DB2 //$NON-NLS-1$ + "INVOKER", //$NON-NLS-1$ + "IS", // DB2 //$NON-NLS-1$ + "ISAM", //$NON-NLS-1$ + "ISNULL", //$NON-NLS-1$ + "ISOBID", // DB2 //$NON-NLS-1$ + "ISOLATION", // DB2 //$NON-NLS-1$ + "ITERATE", // DB2 //$NON-NLS-1$ + "JAR", // DB2 //$NON-NLS-1$ + "JAVA", // DB2 //$NON-NLS-1$ + "JOIN", // DB2 //$NON-NLS-1$ + "K", //$NON-NLS-1$ + "KEY", // DB2 //$NON-NLS-1$ + "KEY_MEMBER", //$NON-NLS-1$ + "KEY_TYPE", //$NON-NLS-1$ + "KEYS", //$NON-NLS-1$ + "KILL", //$NON-NLS-1$ + "LABEL", // DB2 //$NON-NLS-1$ + "LANCOMPILER", //$NON-NLS-1$ + "LANGUAGE", // DB2 //$NON-NLS-1$ + "LARGE", //$NON-NLS-1$ + "LAST", //$NON-NLS-1$ + "LAST_INSERT_ID", //$NON-NLS-1$ + "LATERAL", //$NON-NLS-1$ + "LC_CTYPE", // DB2 //$NON-NLS-1$ + "LEADING", //$NON-NLS-1$ + "LEAST", //$NON-NLS-1$ + "LEAVE", // DB2 //$NON-NLS-1$ + "LEFT", // DB2 //$NON-NLS-1$ + "LENGTH", //$NON-NLS-1$ + "LESS", //$NON-NLS-1$ + "LEVEL", //$NON-NLS-1$ + "LIKE", // DB2 //$NON-NLS-1$ + "LIMIT", //$NON-NLS-1$ + "LINENO", //$NON-NLS-1$ + "LINES", //$NON-NLS-1$ + "LINKTYPE", // DB2 //$NON-NLS-1$ + "LISTEN", //$NON-NLS-1$ + "LN", //$NON-NLS-1$ + "LOAD", //$NON-NLS-1$ + "LOCAL", // DB2 //$NON-NLS-1$ + "LOCALE", // DB2 //$NON-NLS-1$ + "LOCALTIME", //$NON-NLS-1$ + "LOCALTIMESTAMP", //$NON-NLS-1$ + "LOCATION", //$NON-NLS-1$ + "LOCATOR", // DB2 //$NON-NLS-1$ + "LOCATORS", // DB2 //$NON-NLS-1$ + "LOCK", // DB2 //$NON-NLS-1$ + "LOCKMAX", // DB2 //$NON-NLS-1$ + "LOCKSIZE", // DB2 //$NON-NLS-1$ + "LOGIN", //$NON-NLS-1$ + "LOGS", //$NON-NLS-1$ + "LONG", // DB2 //$NON-NLS-1$ + "LONGBLOB", //$NON-NLS-1$ + "LONGTEXT", //$NON-NLS-1$ + "LOOP", // DB2 //$NON-NLS-1$ + "LOW_PRIORITY", //$NON-NLS-1$ + "LOWER", //$NON-NLS-1$ + "M", //$NON-NLS-1$ + "MAP", //$NON-NLS-1$ + "MATCH", //$NON-NLS-1$ + "MATCHED", //$NON-NLS-1$ + "MAX", //$NON-NLS-1$ + "MAX_ROWS", //$NON-NLS-1$ + "MAXEXTENTS", //$NON-NLS-1$ + "MAXVALUE", // DB2 //$NON-NLS-1$ + "MEDIUMBLOB", //$NON-NLS-1$ + "MEDIUMINT", //$NON-NLS-1$ + "MEDIUMTEXT", //$NON-NLS-1$ + "MEMBER", //$NON-NLS-1$ + "MERGE", //$NON-NLS-1$ + "MESSAGE_LENGTH", //$NON-NLS-1$ + "MESSAGE_OCTET_LENGTH", //$NON-NLS-1$ + "MESSAGE_TEXT", //$NON-NLS-1$ + "METHOD", //$NON-NLS-1$ + "MICROSECOND", // DB2 //$NON-NLS-1$ + "MICROSECONDS", // DB2 //$NON-NLS-1$ + "MIDDLEINT", //$NON-NLS-1$ + "MIN", //$NON-NLS-1$ + "MIN_ROWS", //$NON-NLS-1$ + "MINUS", //$NON-NLS-1$ + "MINUTE", // DB2 //$NON-NLS-1$ + "MINUTE_MICROSECOND", //$NON-NLS-1$ + "MINUTE_SECOND", //$NON-NLS-1$ + "MINUTES", // DB2 //$NON-NLS-1$ + "MINVALUE", // DB2 //$NON-NLS-1$ + "MLSLABEL", //$NON-NLS-1$ + "MOD", //$NON-NLS-1$ + "MODE", // DB2 //$NON-NLS-1$ + "MODIFIES", // DB2 //$NON-NLS-1$ + "MODIFY", //$NON-NLS-1$ + "MODULE", //$NON-NLS-1$ + "MONTH", // DB2 //$NON-NLS-1$ + "MONTHNAME", //$NON-NLS-1$ + "MONTHS", // DB2 //$NON-NLS-1$ + "MORE", //$NON-NLS-1$ + "MOVE", //$NON-NLS-1$ + "MULTISET", //$NON-NLS-1$ + "MUMPS", //$NON-NLS-1$ + "MYISAM", //$NON-NLS-1$ + "NAME", //$NON-NLS-1$ + "NAMES", //$NON-NLS-1$ + "NATIONAL", //$NON-NLS-1$ + "NATURAL", //$NON-NLS-1$ + "NCHAR", //$NON-NLS-1$ + "NCLOB", //$NON-NLS-1$ + "NESTING", //$NON-NLS-1$ + "NEW", // DB2 //$NON-NLS-1$ + "NEW_TABLE", // DB2 //$NON-NLS-1$ + "NEXT", //$NON-NLS-1$ + "NO", // DB2 //$NON-NLS-1$ + "NO_WRITE_TO_BINLOG", //$NON-NLS-1$ + "NOAUDIT", //$NON-NLS-1$ + "NOCACHE", // DB2 //$NON-NLS-1$ + "NOCHECK", //$NON-NLS-1$ + "NOCOMPRESS", //$NON-NLS-1$ + "NOCREATEDB", //$NON-NLS-1$ + "NOCREATEROLE", //$NON-NLS-1$ + "NOCREATEUSER", //$NON-NLS-1$ + "NOCYCLE", // DB2 //$NON-NLS-1$ + "NODENAME", // DB2 //$NON-NLS-1$ + "NODENUMBER", // DB2 //$NON-NLS-1$ + "NOINHERIT", //$NON-NLS-1$ + "NOLOGIN", //$NON-NLS-1$ + "NOMAXVALUE", // DB2 //$NON-NLS-1$ + "NOMINVALUE", // DB2 //$NON-NLS-1$ + "NONCLUSTERED", //$NON-NLS-1$ + "NONE", //$NON-NLS-1$ + "NOORDER", // DB2 //$NON-NLS-1$ + "NORMALIZE", //$NON-NLS-1$ + "NORMALIZED", //$NON-NLS-1$ + "NOSUPERUSER", //$NON-NLS-1$ + "NOT", // DB2 //$NON-NLS-1$ + "NOTHING", //$NON-NLS-1$ + "NOTIFY", //$NON-NLS-1$ + "NOTNULL", //$NON-NLS-1$ + "NOWAIT", //$NON-NLS-1$ + "NULL", // DB2 //$NON-NLS-1$ + "NULLABLE", //$NON-NLS-1$ + "NULLIF", //$NON-NLS-1$ + "NULLS", // DB2 //$NON-NLS-1$ + "NUMBER", //$NON-NLS-1$ + "NUMERIC", //$NON-NLS-1$ + "NUMPARTS", // DB2 //$NON-NLS-1$ + "OBID", // DB2 //$NON-NLS-1$ + "OBJECT", //$NON-NLS-1$ + "OCTET_LENGTH", //$NON-NLS-1$ + "OCTETS", //$NON-NLS-1$ + "OF", // DB2 //$NON-NLS-1$ + "OFF", //$NON-NLS-1$ + "OFFLINE", //$NON-NLS-1$ + "OFFSET", //$NON-NLS-1$ + "OFFSETS", //$NON-NLS-1$ + "OIDS", //$NON-NLS-1$ + "OLD", // DB2 //$NON-NLS-1$ + "OLD_TABLE", // DB2 //$NON-NLS-1$ + "ON", // DB2 //$NON-NLS-1$ + "ONLINE", //$NON-NLS-1$ + "ONLY", //$NON-NLS-1$ + "OPEN", // DB2 //$NON-NLS-1$ + "OPENDATASOURCE", //$NON-NLS-1$ + "OPENQUERY", //$NON-NLS-1$ + "OPENROWSET", //$NON-NLS-1$ + "OPENXML", //$NON-NLS-1$ + "OPERATION", //$NON-NLS-1$ + "OPERATOR", //$NON-NLS-1$ + "OPTIMIZATION", // DB2 //$NON-NLS-1$ + "OPTIMIZE", // DB2 //$NON-NLS-1$ + "OPTION", // DB2 //$NON-NLS-1$ + "OPTIONALLY", //$NON-NLS-1$ + "OPTIONS", //$NON-NLS-1$ + "OR", // DB2 //$NON-NLS-1$ + "ORDER", // DB2 //$NON-NLS-1$ + "ORDERING", //$NON-NLS-1$ + "ORDINALITY", //$NON-NLS-1$ + "OTHERS", //$NON-NLS-1$ + "OUT", // DB2 //$NON-NLS-1$ + "OUTER", // DB2 //$NON-NLS-1$ + "OUTFILE", //$NON-NLS-1$ + "OUTPUT", //$NON-NLS-1$ + "OVER", //$NON-NLS-1$ + "OVERLAPS", //$NON-NLS-1$ + "OVERLAY", //$NON-NLS-1$ + "OVERRIDING", // DB2 //$NON-NLS-1$ + "OWNER", //$NON-NLS-1$ + "PACK_KEYS", //$NON-NLS-1$ + "PACKAGE", // DB2 //$NON-NLS-1$ + "PAD", //$NON-NLS-1$ + "PARAMETER", // DB2 //$NON-NLS-1$ + "PARAMETER_MODE", //$NON-NLS-1$ + "PARAMETER_NAME", //$NON-NLS-1$ + "PARAMETER_ORDINAL_POSITION", //$NON-NLS-1$ + "PARAMETER_SPECIFIC_CATALOG", //$NON-NLS-1$ + "PARAMETER_SPECIFIC_NAME", //$NON-NLS-1$ + "PARAMETER_SPECIFIC_SCHEMA", //$NON-NLS-1$ + "PARAMETERS", //$NON-NLS-1$ + "PART", // DB2 //$NON-NLS-1$ + "PARTIAL", //$NON-NLS-1$ + "PARTITION", // DB2 //$NON-NLS-1$ + "PASCAL", //$NON-NLS-1$ + "PASSWORD", //$NON-NLS-1$ + "PATH", // DB2 //$NON-NLS-1$ + "PCTFREE", //$NON-NLS-1$ + "PERCENT", //$NON-NLS-1$ + "PERCENT_RANK", //$NON-NLS-1$ + "PERCENTILE_CONT", //$NON-NLS-1$ + "PERCENTILE_DISC", //$NON-NLS-1$ + "PIECESIZE", // DB2 //$NON-NLS-1$ + "PLACING", //$NON-NLS-1$ + "PLAN", // DB2 //$NON-NLS-1$ + "PLI", //$NON-NLS-1$ + "POSITION", // DB2 //$NON-NLS-1$ + "POSTFIX", //$NON-NLS-1$ + "POWER", //$NON-NLS-1$ + "PRECEDING", //$NON-NLS-1$ + "PRECISION", // DB2 //$NON-NLS-1$ + "PREFIX", //$NON-NLS-1$ + "PREORDER", //$NON-NLS-1$ + "PREPARE", // DB2 //$NON-NLS-1$ + "PREPARED", //$NON-NLS-1$ + "PRESERVE", //$NON-NLS-1$ + "PRIMARY", // DB2 //$NON-NLS-1$ + "PRINT", //$NON-NLS-1$ + "PRIOR", //$NON-NLS-1$ + "PRIQTY", // DB2 //$NON-NLS-1$ + "PRIVILEGES", // DB2 //$NON-NLS-1$ + "PROC", //$NON-NLS-1$ + "PROCEDURAL", //$NON-NLS-1$ + "PROCEDURE", // DB2 //$NON-NLS-1$ + "PROCESS", //$NON-NLS-1$ + "PROCESSLIST", //$NON-NLS-1$ + "PROGRAM", // DB2 //$NON-NLS-1$ + "PSID", // DB2 //$NON-NLS-1$ + "PUBLIC", //$NON-NLS-1$ + "PURGE", //$NON-NLS-1$ + "QUERYNO", // DB2 //$NON-NLS-1$ + "QUOTE", //$NON-NLS-1$ + "RAID0", //$NON-NLS-1$ + "RAISERROR", //$NON-NLS-1$ + "RANGE", //$NON-NLS-1$ + "RANK", //$NON-NLS-1$ + "RAW", //$NON-NLS-1$ + "READ", // DB2 //$NON-NLS-1$ + "READS", // DB2 //$NON-NLS-1$ + "READTEXT", //$NON-NLS-1$ + "REAL", //$NON-NLS-1$ + "RECHECK", //$NON-NLS-1$ + "RECONFIGURE", //$NON-NLS-1$ + "RECOVERY", // DB2 //$NON-NLS-1$ + "RECURSIVE", //$NON-NLS-1$ + "REF", //$NON-NLS-1$ + "REFERENCES", // DB2 //$NON-NLS-1$ + "REFERENCING", // DB2 //$NON-NLS-1$ + "REGEXP", //$NON-NLS-1$ + "REGR_AVGX", //$NON-NLS-1$ + "REGR_AVGY", //$NON-NLS-1$ + "REGR_COUNT", //$NON-NLS-1$ + "REGR_INTERCEPT", //$NON-NLS-1$ + "REGR_R2", //$NON-NLS-1$ + "REGR_SLOPE", //$NON-NLS-1$ + "REGR_SXX", //$NON-NLS-1$ + "REGR_SXY", //$NON-NLS-1$ + "REGR_SYY", //$NON-NLS-1$ + "REINDEX", //$NON-NLS-1$ + "RELATIVE", //$NON-NLS-1$ + "RELEASE", // DB2 //$NON-NLS-1$ + "RELOAD", //$NON-NLS-1$ + "RENAME", // DB2 //$NON-NLS-1$ + "REPEAT", // DB2 //$NON-NLS-1$ + "REPEATABLE", //$NON-NLS-1$ + "REPLACE", //$NON-NLS-1$ + "REPLICATION", //$NON-NLS-1$ + "REQUIRE", //$NON-NLS-1$ + "RESET", // DB2 //$NON-NLS-1$ + "RESIGNAL", // DB2 //$NON-NLS-1$ + "RESOURCE", //$NON-NLS-1$ + "RESTART", // DB2 //$NON-NLS-1$ + "RESTORE", //$NON-NLS-1$ + "RESTRICT", // DB2 //$NON-NLS-1$ + "RESULT", // DB2 //$NON-NLS-1$ + "RESULT_SET_LOCATOR", // DB2 //$NON-NLS-1$ + "RETURN", // DB2 //$NON-NLS-1$ + "RETURNED_CARDINALITY", //$NON-NLS-1$ + "RETURNED_LENGTH", //$NON-NLS-1$ + "RETURNED_OCTET_LENGTH", //$NON-NLS-1$ + "RETURNED_SQLSTATE", //$NON-NLS-1$ + "RETURNS", // DB2 //$NON-NLS-1$ + "REVOKE", // DB2 //$NON-NLS-1$ + "RIGHT", // DB2 //$NON-NLS-1$ + "RLIKE", //$NON-NLS-1$ + "ROLE", //$NON-NLS-1$ + "ROLLBACK", // DB2 //$NON-NLS-1$ + "ROLLUP", //$NON-NLS-1$ + "ROUTINE", // DB2 //$NON-NLS-1$ + "ROUTINE_CATALOG", //$NON-NLS-1$ + "ROUTINE_NAME", //$NON-NLS-1$ + "ROUTINE_SCHEMA", //$NON-NLS-1$ + "ROW", // DB2 //$NON-NLS-1$ + "ROW_COUNT", //$NON-NLS-1$ + "ROW_NUMBER", //$NON-NLS-1$ + "ROWCOUNT", //$NON-NLS-1$ + "ROWGUIDCOL", //$NON-NLS-1$ + "ROWID", //$NON-NLS-1$ + "ROWNUM", //$NON-NLS-1$ + "ROWS", // DB2 //$NON-NLS-1$ + "RRN", // DB2 //$NON-NLS-1$ + "RULE", //$NON-NLS-1$ + "RUN", // DB2 //$NON-NLS-1$ + "SAVE", //$NON-NLS-1$ + "SAVEPOINT", // DB2 //$NON-NLS-1$ + "SCALE", //$NON-NLS-1$ + "SCHEMA", // DB2 //$NON-NLS-1$ + "SCHEMA_NAME", //$NON-NLS-1$ + "SCHEMAS", //$NON-NLS-1$ + "SCOPE", //$NON-NLS-1$ + "SCOPE_CATALOG", //$NON-NLS-1$ + "SCOPE_NAME", //$NON-NLS-1$ + "SCOPE_SCHEMA", //$NON-NLS-1$ + "SCRATCHPAD", // DB2 //$NON-NLS-1$ + "SCROLL", //$NON-NLS-1$ + "SEARCH", //$NON-NLS-1$ + "SECOND", // DB2 //$NON-NLS-1$ + "SECOND_MICROSECOND", //$NON-NLS-1$ + "SECONDS", // DB2 //$NON-NLS-1$ + "SECQTY", // DB2 //$NON-NLS-1$ + "SECTION", //$NON-NLS-1$ + "SECURITY", // DB2 //$NON-NLS-1$ + "SELECT", // DB2 //$NON-NLS-1$ + "SELF", //$NON-NLS-1$ + "SENSITIVE", // DB2 //$NON-NLS-1$ + "SEPARATOR", //$NON-NLS-1$ + "SEQUENCE", //$NON-NLS-1$ + "SERIALIZABLE", //$NON-NLS-1$ + "SERVER_NAME", //$NON-NLS-1$ + "SESSION", //$NON-NLS-1$ + "SESSION_USER", //$NON-NLS-1$ + "SET", // DB2 //$NON-NLS-1$ + "SETOF", //$NON-NLS-1$ + "SETS", //$NON-NLS-1$ + "SETUSER", //$NON-NLS-1$ + "SHARE", //$NON-NLS-1$ + "SHOW", //$NON-NLS-1$ + "SHUTDOWN", //$NON-NLS-1$ + "SIGNAL", // DB2 //$NON-NLS-1$ + "SIMILAR", //$NON-NLS-1$ + "SIMPLE", // DB2 //$NON-NLS-1$ + "SIZE", //$NON-NLS-1$ + "SMALLINT", //$NON-NLS-1$ + "SOME", // DB2 //$NON-NLS-1$ + "SONAME", //$NON-NLS-1$ + "SOURCE", // DB2 //$NON-NLS-1$ + "SPACE", //$NON-NLS-1$ + "SPATIAL", //$NON-NLS-1$ + "SPECIFIC", // DB2 //$NON-NLS-1$ + "SPECIFIC_NAME", //$NON-NLS-1$ + "SPECIFICTYPE", //$NON-NLS-1$ + "SQL", // DB2 //$NON-NLS-1$ + "SQL_BIG_RESULT", //$NON-NLS-1$ + "SQL_BIG_SELECTS", //$NON-NLS-1$ + "SQL_BIG_TABLES", //$NON-NLS-1$ + "SQL_CALC_FOUND_ROWS", //$NON-NLS-1$ + "SQL_LOG_OFF", //$NON-NLS-1$ + "SQL_LOG_UPDATE", //$NON-NLS-1$ + "SQL_LOW_PRIORITY_UPDATES", //$NON-NLS-1$ + "SQL_SELECT_LIMIT", //$NON-NLS-1$ + "SQL_SMALL_RESULT", //$NON-NLS-1$ + "SQL_WARNINGS", //$NON-NLS-1$ + "SQLCA", //$NON-NLS-1$ + "SQLCODE", //$NON-NLS-1$ + "SQLERROR", //$NON-NLS-1$ + "SQLEXCEPTION", //$NON-NLS-1$ + "SQLID", // DB2 //$NON-NLS-1$ + "SQLSTATE", //$NON-NLS-1$ + "SQLWARNING", //$NON-NLS-1$ + "SQRT", //$NON-NLS-1$ + "SSL", //$NON-NLS-1$ + "STABLE", //$NON-NLS-1$ + "STANDARD", // DB2 //$NON-NLS-1$ + "START", // DB2 //$NON-NLS-1$ + "STARTING", //$NON-NLS-1$ + "STATE", //$NON-NLS-1$ + "STATEMENT", //$NON-NLS-1$ + "STATIC", // DB2 //$NON-NLS-1$ + "STATISTICS", //$NON-NLS-1$ + "STATUS", //$NON-NLS-1$ + "STAY", // DB2 //$NON-NLS-1$ + "STDDEV_POP", //$NON-NLS-1$ + "STDDEV_SAMP", //$NON-NLS-1$ + "STDIN", //$NON-NLS-1$ + "STDOUT", //$NON-NLS-1$ + "STOGROUP", // DB2 //$NON-NLS-1$ + "STORAGE", //$NON-NLS-1$ + "STORES", // DB2 //$NON-NLS-1$ + "STRAIGHT_JOIN", //$NON-NLS-1$ + "STRICT", //$NON-NLS-1$ + "STRING", //$NON-NLS-1$ + "STRUCTURE", //$NON-NLS-1$ + "STYLE", // DB2 //$NON-NLS-1$ + "SUBCLASS_ORIGIN", //$NON-NLS-1$ + "SUBLIST", //$NON-NLS-1$ + "SUBMULTISET", //$NON-NLS-1$ + "SUBPAGES", // DB2 //$NON-NLS-1$ + "SUBSTRING", // DB2 //$NON-NLS-1$ + "SUCCESSFUL", //$NON-NLS-1$ + "SUM", //$NON-NLS-1$ + "SUPERUSER", //$NON-NLS-1$ + "SYMMETRIC", //$NON-NLS-1$ + "SYNONYM", // DB2 //$NON-NLS-1$ + "SYSDATE", //$NON-NLS-1$ + "SYSFUN", // DB2 //$NON-NLS-1$ + "SYSIBM", // DB2 //$NON-NLS-1$ + "SYSID", //$NON-NLS-1$ + "SYSPROC", // DB2 //$NON-NLS-1$ + "SYSTEM", // DB2 //$NON-NLS-1$ + "SYSTEM_USER", //$NON-NLS-1$ + "TABLE", // DB2 //$NON-NLS-1$ + "TABLE_NAME", //$NON-NLS-1$ + "TABLES", //$NON-NLS-1$ + "TABLESAMPLE", //$NON-NLS-1$ + "TABLESPACE", // DB2 //$NON-NLS-1$ + "TEMP", //$NON-NLS-1$ + "TEMPLATE", //$NON-NLS-1$ + "TEMPORARY", //$NON-NLS-1$ + "TERMINATE", //$NON-NLS-1$ + "TERMINATED", //$NON-NLS-1$ + "TEXT", //$NON-NLS-1$ + "TEXTSIZE", //$NON-NLS-1$ + "THAN", //$NON-NLS-1$ + "THEN", // DB2 //$NON-NLS-1$ + "TIES", //$NON-NLS-1$ + "TIME", //$NON-NLS-1$ + "TIMESTAMP", //$NON-NLS-1$ + "TIMEZONE_HOUR", //$NON-NLS-1$ + "TIMEZONE_MINUTE", //$NON-NLS-1$ + "TINYBLOB", //$NON-NLS-1$ + "TINYINT", //$NON-NLS-1$ + "TINYTEXT", //$NON-NLS-1$ + "TO", // DB2 //$NON-NLS-1$ + "TOAST", //$NON-NLS-1$ + "TOP", //$NON-NLS-1$ + "TOP_LEVEL_COUNT", //$NON-NLS-1$ + "TRAILING", //$NON-NLS-1$ + "TRAN", //$NON-NLS-1$ + "TRANSACTION", // DB2 //$NON-NLS-1$ + "TRANSACTION_ACTIVE", //$NON-NLS-1$ + "TRANSACTIONS_COMMITTED", //$NON-NLS-1$ + "TRANSACTIONS_ROLLED_BACK", //$NON-NLS-1$ + "TRANSFORM", //$NON-NLS-1$ + "TRANSFORMS", //$NON-NLS-1$ + "TRANSLATE", //$NON-NLS-1$ + "TRANSLATION", //$NON-NLS-1$ + "TREAT", //$NON-NLS-1$ + "TRIGGER", // DB2 //$NON-NLS-1$ + "TRIGGER_CATALOG", //$NON-NLS-1$ + "TRIGGER_NAME", //$NON-NLS-1$ + "TRIGGER_SCHEMA", //$NON-NLS-1$ + "TRIM", // DB2 //$NON-NLS-1$ + "TRUE", //$NON-NLS-1$ + "TRUNCATE", //$NON-NLS-1$ + "TRUSTED", //$NON-NLS-1$ + "TSEQUAL", //$NON-NLS-1$ + "TYPE", // DB2 //$NON-NLS-1$ + "UESCAPE", //$NON-NLS-1$ + "UID", //$NON-NLS-1$ + "UNBOUNDED", //$NON-NLS-1$ + "UNCOMMITTED", //$NON-NLS-1$ + "UNDER", //$NON-NLS-1$ + "UNDO", // DB2 //$NON-NLS-1$ + "UNENCRYPTED", //$NON-NLS-1$ + "UNION", // DB2 //$NON-NLS-1$ + "UNIQUE", // DB2 //$NON-NLS-1$ + "UNKNOWN", //$NON-NLS-1$ + "UNLISTEN", //$NON-NLS-1$ + "UNLOCK", //$NON-NLS-1$ + "UNNAMED", //$NON-NLS-1$ + "UNNEST", //$NON-NLS-1$ + "UNSIGNED", //$NON-NLS-1$ + "UNTIL", // DB2 //$NON-NLS-1$ + "UPDATE", // DB2 //$NON-NLS-1$ + "UPDATETEXT", //$NON-NLS-1$ + "UPPER", //$NON-NLS-1$ + "USAGE", // DB2 //$NON-NLS-1$ + "USE", //$NON-NLS-1$ + "USER", // DB2 //$NON-NLS-1$ + "USER_DEFINED_TYPE_CATALOG", //$NON-NLS-1$ + "USER_DEFINED_TYPE_CODE", //$NON-NLS-1$ + "USER_DEFINED_TYPE_NAME", //$NON-NLS-1$ + "USER_DEFINED_TYPE_SCHEMA", //$NON-NLS-1$ + "USING", // DB2 //$NON-NLS-1$ + "UTC_DATE", //$NON-NLS-1$ + "UTC_TIME", //$NON-NLS-1$ + "UTC_TIMESTAMP", //$NON-NLS-1$ + "VACUUM", //$NON-NLS-1$ + "VALID", //$NON-NLS-1$ + "VALIDATE", //$NON-NLS-1$ + "VALIDATOR", //$NON-NLS-1$ + "VALIDPROC", // DB2 //$NON-NLS-1$ + "VALUE", //$NON-NLS-1$ + "VALUES", // DB2 //$NON-NLS-1$ + "VAR_POP", //$NON-NLS-1$ + "VAR_SAMP", //$NON-NLS-1$ + "VARBINARY", //$NON-NLS-1$ + "VARCHAR", //$NON-NLS-1$ + "VARCHAR2", //$NON-NLS-1$ + "VARCHARACTER", //$NON-NLS-1$ + "VARIABLE", // DB2 //$NON-NLS-1$ + "VARIABLES", //$NON-NLS-1$ + "VARIANT", // DB2 //$NON-NLS-1$ + "VARYING", //$NON-NLS-1$ + "VCAT", // DB2 //$NON-NLS-1$ + "VERBOSE", //$NON-NLS-1$ + "VIEW", // DB2 //$NON-NLS-1$ + "VOLATILE", //$NON-NLS-1$ + "VOLUMES", // DB2 //$NON-NLS-1$ + "WAITFOR", //$NON-NLS-1$ + "WHEN", // DB2 //$NON-NLS-1$ + "WHENEVER", //$NON-NLS-1$ + "WHERE", // DB2 //$NON-NLS-1$ + "WHILE", // DB2 //$NON-NLS-1$ + "WIDTH_BUCKET", //$NON-NLS-1$ + "WINDOW", //$NON-NLS-1$ + "WITH", // DB2 //$NON-NLS-1$ + "WITHIN", //$NON-NLS-1$ + "WITHOUT", //$NON-NLS-1$ + "WLM", // DB2 //$NON-NLS-1$ + "WORK", //$NON-NLS-1$ + "WRITE", // DB2 //$NON-NLS-1$ + "WRITETEXT", //$NON-NLS-1$ + "X509", //$NON-NLS-1$ + "XOR", //$NON-NLS-1$ + "YEAR", // DB2 //$NON-NLS-1$ + "YEAR_MONTH", //$NON-NLS-1$ + "YEARS", // DB2 //$NON-NLS-1$ + "ZEROFILL", //$NON-NLS-1$ + "ZONE" //$NON-NLS-1$ + }; + + RESERVED_WORDS = new HashSet(words.length); + + for (String word : words) { + RESERVED_WORDS.add(word); + } + } + + public static boolean containsWord(String word) { + boolean rc; + + if (word == null) { + rc = false; + } else { + rc = RESERVED_WORDS.contains(word.toUpperCase()); + } + + return rc; + } + + /** + * Utility class - no instances allowed + */ + private SqlReservedWords() { + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/ConditionalModelRules.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/ConditionalModelRules.java new file mode 100644 index 0000000..3a14adf --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/ConditionalModelRules.java @@ -0,0 +1,76 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.rules; + +import org.mybatis.generator.api.IntrospectedTable; + +/** + * This class encapsulates all the code generation rules for a table using the + * conditional model. In this model we do not generate primary key or record + * with BLOBs classes if the class would only hold one field. + * + * @author Jeff Butler + * + */ +public class ConditionalModelRules extends BaseRules { + + /** + * + */ + public ConditionalModelRules(IntrospectedTable introspectedTable) { + super(introspectedTable); + } + + /** + * We generate a primary key if there is more than one primary key field. + * + * @return true if the primary key should be generated + */ + public boolean generatePrimaryKeyClass() { + return introspectedTable.getPrimaryKeyColumns().size() > 1; + } + + /** + * Generate a base record if there are any base columns, or if there is only + * one primary key coulmn (in which case we will not generate a primary key + * class), or if there is only one BLOB column (in which case we will not + * generate a record with BLOBs class). + * + * @return true if the class should be generated + */ + public boolean generateBaseRecordClass() { + return introspectedTable.getBaseColumns().size() > 0 + || introspectedTable.getPrimaryKeyColumns().size() == 1 + || (introspectedTable.getBLOBColumns().size() > 0 && !generateRecordWithBLOBsClass()); + + } + + /** + * We generate a record with BLOBs class if there is more than one BLOB + * column. Do not generate a BLOBs class if any other super class would only + * contain one field + * + * @return true if the record with BLOBs class should be generated + */ + public boolean generateRecordWithBLOBsClass() { + int otherColumnCount = introspectedTable.getPrimaryKeyColumns().size() + + introspectedTable.getBaseColumns().size(); + + return otherColumnCount > 1 + && introspectedTable.getBLOBColumns().size() > 1; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/FlatModelRules.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/FlatModelRules.java new file mode 100644 index 0000000..c076fba --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/FlatModelRules.java @@ -0,0 +1,63 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.rules; + +import org.mybatis.generator.api.IntrospectedTable; + +/** + * This class encapsulates all the code generation rules for a table using the + * flat model. + * + * @author Jeff Butler + * + */ +public class FlatModelRules extends BaseRules { + + /** + * + */ + public FlatModelRules(IntrospectedTable introspectedTable) { + super(introspectedTable); + } + + /** + * We never generate a primary key in the flat model. + * + * @return true if the primary key should be generated + */ + public boolean generatePrimaryKeyClass() { + return false; + } + + /** + * We always generate a base record in the flat model. + * + * @return true if the class should be generated + */ + public boolean generateBaseRecordClass() { + return true; + } + + /** + * We never generate a record with BLOBs class in the flat model. + * + * @return true if the record with BLOBs class should be generated + */ + public boolean generateRecordWithBLOBsClass() { + return false; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/HierarchicalModelRules.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/HierarchicalModelRules.java new file mode 100644 index 0000000..93a7bc3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/HierarchicalModelRules.java @@ -0,0 +1,68 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.rules; + +import org.mybatis.generator.api.IntrospectedTable; + +/** + * This class encapsulates all the code generation rules for a table using the + * hierarchical model. + * + * @author Jeff Butler + * + */ +public class HierarchicalModelRules extends BaseRules { + + /** + * + */ + public HierarchicalModelRules(IntrospectedTable introspectedTable) { + super(introspectedTable); + } + + /** + * Implements the rule for determining whether to generate a primary key + * class. If the physical table has a primary key, then we generate the + * class. + * + * @return true if the primary key should be generated + */ + public boolean generatePrimaryKeyClass() { + return introspectedTable.hasPrimaryKeyColumns(); + } + + /** + * Implements the rule for generating a base record. If the table has fields + * that are not in the primary key, and non-BLOB fields, then generate the + * class. + * + * @return true if the class should be generated + */ + public boolean generateBaseRecordClass() { + return introspectedTable.hasBaseColumns(); + } + + /** + * Implements the rule for generating a record with BLOBs. A record with + * BLOBs is generated if the table contains any BLOB fields. + * + * @return true if the record with BLOBs class should be generated + */ + public boolean generateRecordWithBLOBsClass() { + return introspectedTable.hasBLOBColumns(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/Rules.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/Rules.java new file mode 100644 index 0000000..e3d5c2c --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/Rules.java @@ -0,0 +1,250 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.rules; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; + +/** + * This interface centralizes all the rules related to code generation - + * including the methods and objects to create, and certain attributes related + * to those objects. + * + * @author Jeff Butler + */ +public interface Rules { + + /** + * Implements the rule for generating the insert SQL Map element and DAO + * method. If the insert statement is allowed, then generate the element and + * method. + * + * @return true if the element and method should be generated + */ + boolean generateInsert(); + + /** + * Implements the rule for generating the insert selective SQL Map element + * and DAO method. If the insert statement is allowed, then generate the + * element and method. + * + * @return true if the element and method should be generated + */ + boolean generateInsertSelective(); + + /** + * Calculates the class that contains all fields. This class is used as the + * insert statement parameter, as well as the returned value from the select + * by primary key method. The actual class depends on how the domain model + * is generated. + * + * @return the type of the class that holds all fields + */ + FullyQualifiedJavaType calculateAllFieldsClass(); + + /** + * Implements the rule for generating the update by primary key without + * BLOBs SQL Map element and DAO method. If the table has a primary key as + * well as other non-BLOB fields, and the updateByPrimaryKey statement is + * allowed, then generate the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateUpdateByPrimaryKeyWithoutBLOBs(); + + /** + * Implements the rule for generating the update by primary key with BLOBs + * SQL Map element and DAO method. If the table has a primary key as well as + * other BLOB fields, and the updateByPrimaryKey statement is allowed, then + * generate the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateUpdateByPrimaryKeyWithBLOBs(); + + /** + * Implements the rule for generating the update by primary key selective + * SQL Map element and DAO method. If the table has a primary key as well as + * other fields, and the updateByPrimaryKey statement is allowed, then + * generate the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateUpdateByPrimaryKeySelective(); + + /** + * Implements the rule for generating the delete by primary key SQL Map + * element and DAO method. If the table has a primary key, and the + * deleteByPrimaryKey statement is allowed, then generate the element and + * method. + * + * @return true if the element and method should be generated + */ + boolean generateDeleteByPrimaryKey(); + + /** + * Implements the rule for generating the delete by example SQL Map element + * and DAO method. If the deleteByExample statement is allowed, then + * generate the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateDeleteByExample(); + + /** + * Implements the rule for generating the result map without BLOBs. If + * either select method is allowed, then generate the result map. + * + * @return true if the result map should be generated + */ + boolean generateBaseResultMap(); + + /** + * Implements the rule for generating the result map with BLOBs. If the + * table has BLOB columns, and either select method is allowed, then + * generate the result map. + * + * @return true if the result map should be generated + */ + boolean generateResultMapWithBLOBs(); + + /** + * Implements the rule for generating the SQL example where clause element. + * + * In iBATIS2, generate the element if the selectByExample, deleteByExample, + * updateByExample, or countByExample statements are allowed. + * + * In MyBatis3, generate the element if the selectByExample, + * deleteByExample, or countByExample statements are allowed. + * + * @return true if the SQL where clause element should be generated + */ + boolean generateSQLExampleWhereClause(); + + /** + * Implements the rule for generating the SQL example where clause element + * specifically for use in the update by example methods. + * + * In iBATIS2, do not generate the element. + * + * In MyBatis, generate the element if the updateByExample statements are + * allowed. + * + * @return true if the SQL where clause element should be generated + */ + boolean generateMyBatis3UpdateByExampleWhereClause(); + + /** + * Implements the rule for generating the SQL base column list element. + * Generate the element if any of the select methods are enabled. + * + * @return true if the SQL base column list element should be generated + */ + boolean generateBaseColumnList(); + + /** + * Implements the rule for generating the SQL blob column list element. + * Generate the element if any of the select methods are enabled, and the + * table contains BLOB columns. + * + * @return true if the SQL blob column list element should be generated + */ + boolean generateBlobColumnList(); + + /** + * Implements the rule for generating the select by primary key SQL Map + * element and DAO method. If the table has a primary key as well as other + * fields, and the selectByPrimaryKey statement is allowed, then generate + * the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateSelectByPrimaryKey(); + + /** + * Implements the rule for generating the select by example without BLOBs + * SQL Map element and DAO method. If the selectByExample statement is + * allowed, then generate the element and method. + * + * @return true if the element and method should be generated + */ + boolean generateSelectByExampleWithoutBLOBs(); + + /** + * Implements the rule for generating the select by example with BLOBs SQL + * Map element and DAO method. If the table has BLOB fields and the + * selectByExample statement is allowed, then generate the element and + * method. + * + * @return true if the element and method should be generated + */ + boolean generateSelectByExampleWithBLOBs(); + + /** + * Implements the rule for generating an example class. The class should be + * generated if the selectByExample or deleteByExample or countByExample + * methods are allowed. + * + * @return true if the example class should be generated + */ + boolean generateExampleClass(); + + boolean generateCountByExample(); + + boolean generateUpdateByExampleSelective(); + + boolean generateUpdateByExampleWithoutBLOBs(); + + boolean generateUpdateByExampleWithBLOBs(); + + /** + * Implements the rule for determining whether to generate a primary key + * class. If you return false from this method, and the table has primary + * key columns, then the primary key columns will be added to the base + * class. + * + * @return true if a separate primary key class should be generated + */ + boolean generatePrimaryKeyClass(); + + /** + * Implements the rule for generating a base record. + * + * @return true if the class should be generated + */ + boolean generateBaseRecordClass(); + + /** + * Implements the rule for generating a record with BLOBs. If you return + * false from this method, and the table had BLOB columns, then the BLOB + * columns will be added to the base class. + * + * @return true if the record with BLOBs class should be generated + */ + boolean generateRecordWithBLOBsClass(); + + /** + * Implements the rule for generating a Java client. This rule is + * only active when a javaClientGenerator configuration has been + * specified, but the table is designated as "modelOnly". Do not + * generate the client if the table is designated as modelOnly. + * + * @return true if the Java client should be generated + */ + boolean generateJavaClient(); + + IntrospectedTable getIntrospectedTable(); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/RulesDelegate.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/RulesDelegate.java new file mode 100644 index 0000000..d6fa430 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/rules/RulesDelegate.java @@ -0,0 +1,175 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.rules; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; + +/** + * This class can be used by plugins to easily implement a custom rules + * implementation. Plugins should respect the rules implementation calculated by + * the generator, as well as implementations from other plugins. In general if + * something is disabled by the default rules, or is disabled by some other + * plugin, it should not be re-enabled. Therefore, the following pattern of use + * is recommended: + * + *

+ * public class MyPlugin extends PluginAdapter {
+ *   @Override
+ *   public void initialized(IntrospectedTable introspectedTable) {
+ *     MyRules myRules = new MyRules(introspectedTable.getRules());
+ *     introspectedTable.setRules(myRules);
+ *   }
+ * }
+ * 
+ * public class MyRules extends RulesDelegate (
+ *   public MyRules(Rules rules) {
+ *     super(rules);
+ *   }
+ *   
+ *   @Override
+ *   public boolean generateInsert() {
+ *     boolean rc = super.generateInsert();
+ *     if (rc) {
+ *       // Other plugins, and the default rules, enable generation
+ *       // of the insert method.  We can decide to disable it here
+ *       // if needed.
+ *     }
+ *     
+ *     return rc;
+ *   }
+ * 
+ * + * + * @author Jeff Butler + * + */ +public class RulesDelegate implements Rules { + protected Rules rules; + + public RulesDelegate(Rules rules) { + this.rules = rules; + } + + public FullyQualifiedJavaType calculateAllFieldsClass() { + return rules.calculateAllFieldsClass(); + } + + public boolean generateBaseRecordClass() { + return rules.generateBaseRecordClass(); + } + + public boolean generateBaseResultMap() { + return rules.generateBaseResultMap(); + } + + public boolean generateCountByExample() { + return rules.generateCountByExample(); + } + + public boolean generateDeleteByExample() { + return rules.generateDeleteByExample(); + } + + public boolean generateDeleteByPrimaryKey() { + return rules.generateDeleteByPrimaryKey(); + } + + public boolean generateExampleClass() { + return rules.generateExampleClass(); + } + + public boolean generateInsert() { + return rules.generateInsert(); + } + + public boolean generateInsertSelective() { + return rules.generateInsertSelective(); + } + + public boolean generatePrimaryKeyClass() { + return rules.generatePrimaryKeyClass(); + } + + public boolean generateRecordWithBLOBsClass() { + return rules.generateRecordWithBLOBsClass(); + } + + public boolean generateResultMapWithBLOBs() { + return rules.generateResultMapWithBLOBs(); + } + + public boolean generateSelectByExampleWithBLOBs() { + return rules.generateSelectByExampleWithBLOBs(); + } + + public boolean generateSelectByExampleWithoutBLOBs() { + return rules.generateSelectByExampleWithoutBLOBs(); + } + + public boolean generateSelectByPrimaryKey() { + return rules.generateSelectByPrimaryKey(); + } + + public boolean generateSQLExampleWhereClause() { + return rules.generateSQLExampleWhereClause(); + } + + public boolean generateMyBatis3UpdateByExampleWhereClause() { + return rules.generateMyBatis3UpdateByExampleWhereClause(); + } + + public boolean generateUpdateByExampleSelective() { + return rules.generateUpdateByExampleSelective(); + } + + public boolean generateUpdateByExampleWithBLOBs() { + return rules.generateUpdateByExampleWithBLOBs(); + } + + public boolean generateUpdateByExampleWithoutBLOBs() { + return rules.generateUpdateByExampleWithoutBLOBs(); + } + + public boolean generateUpdateByPrimaryKeySelective() { + return rules.generateUpdateByPrimaryKeySelective(); + } + + public boolean generateUpdateByPrimaryKeyWithBLOBs() { + return rules.generateUpdateByPrimaryKeyWithBLOBs(); + } + + public boolean generateUpdateByPrimaryKeyWithoutBLOBs() { + return rules.generateUpdateByPrimaryKeyWithoutBLOBs(); + } + + public IntrospectedTable getIntrospectedTable() { + return rules.getIntrospectedTable(); + } + + public boolean generateBaseColumnList() { + return rules.generateBaseColumnList(); + } + + public boolean generateBlobColumnList() { + return rules.generateBlobColumnList(); + } + + public boolean generateJavaClient() { + return rules.generateJavaClient(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JavaTypeResolverDefaultImpl.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JavaTypeResolverDefaultImpl.java new file mode 100644 index 0000000..a4206a5 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JavaTypeResolverDefaultImpl.java @@ -0,0 +1,215 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.types; + +import java.math.BigDecimal; +import java.sql.Types; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.JavaTypeResolver; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.config.Context; +import org.mybatis.generator.config.PropertyRegistry; +import org.mybatis.generator.internal.util.StringUtility; + +/** + * + * @author Jeff Butler + */ +public class JavaTypeResolverDefaultImpl implements JavaTypeResolver { + + protected List warnings; + + protected Properties properties; + + protected Context context; + + protected boolean forceBigDecimals; + + protected Map typeMap; + + public JavaTypeResolverDefaultImpl() { + super(); + properties = new Properties(); + typeMap = new HashMap(); + + typeMap.put(Types.ARRAY, new JdbcTypeInformation("ARRAY", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.BIGINT, new JdbcTypeInformation("BIGINT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Long.class.getName()))); + typeMap.put(Types.BINARY, new JdbcTypeInformation("BINARY", //$NON-NLS-1$ + new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$ + typeMap.put(Types.BIT, new JdbcTypeInformation("BIT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Boolean.class.getName()))); + typeMap.put(Types.BLOB, new JdbcTypeInformation("BLOB", //$NON-NLS-1$ + new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$ + typeMap.put(Types.BOOLEAN, new JdbcTypeInformation("BOOLEAN", //$NON-NLS-1$ + new FullyQualifiedJavaType(Boolean.class.getName()))); + typeMap.put(Types.CHAR, new JdbcTypeInformation("CHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Types.CLOB, new JdbcTypeInformation("CLOB", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Types.DATALINK, new JdbcTypeInformation("DATALINK", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.DATE, new JdbcTypeInformation("TIMESTAMP", //$NON-NLS-1$ + new FullyQualifiedJavaType(Date.class.getName()))); + typeMap.put(Types.DISTINCT, new JdbcTypeInformation("DISTINCT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.DOUBLE, new JdbcTypeInformation("DOUBLE", //$NON-NLS-1$ + new FullyQualifiedJavaType(Double.class.getName()))); + typeMap.put(Types.FLOAT, new JdbcTypeInformation("FLOAT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Double.class.getName()))); + typeMap.put(Types.INTEGER, new JdbcTypeInformation("INTEGER", //$NON-NLS-1$ + new FullyQualifiedJavaType(Integer.class.getName()))); + typeMap.put(Types.JAVA_OBJECT, new JdbcTypeInformation("JAVA_OBJECT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Jdbc4Types.LONGNVARCHAR, new JdbcTypeInformation("LONGNVARCHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Types.LONGVARBINARY, new JdbcTypeInformation( + "LONGVARBINARY", //$NON-NLS-1$ + new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$ + typeMap.put(Types.LONGVARCHAR, new JdbcTypeInformation("LONGVARCHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Jdbc4Types.NCHAR, new JdbcTypeInformation("NCHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Jdbc4Types.NCLOB, new JdbcTypeInformation("NCLOB", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Jdbc4Types.NVARCHAR, new JdbcTypeInformation("NVARCHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + typeMap.put(Types.NULL, new JdbcTypeInformation("NULL", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.OTHER, new JdbcTypeInformation("OTHER", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.REAL, new JdbcTypeInformation("REAL", //$NON-NLS-1$ + new FullyQualifiedJavaType(Float.class.getName()))); + typeMap.put(Types.REF, new JdbcTypeInformation("REF", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Short.class.getName()))); + typeMap.put(Types.STRUCT, new JdbcTypeInformation("STRUCT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Object.class.getName()))); + typeMap.put(Types.TIME, new JdbcTypeInformation("TIME", //$NON-NLS-1$ + new FullyQualifiedJavaType(Date.class.getName()))); + typeMap.put(Types.TIMESTAMP, new JdbcTypeInformation("TIMESTAMP", //$NON-NLS-1$ + new FullyQualifiedJavaType(Date.class.getName()))); + typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT", //$NON-NLS-1$ + new FullyQualifiedJavaType(Byte.class.getName()))); + typeMap.put(Types.VARBINARY, new JdbcTypeInformation("VARBINARY", //$NON-NLS-1$ + new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$ + typeMap.put(Types.VARCHAR, new JdbcTypeInformation("VARCHAR", //$NON-NLS-1$ + new FullyQualifiedJavaType(String.class.getName()))); + + } + + public void addConfigurationProperties(Properties properties) { + this.properties.putAll(properties); + forceBigDecimals = StringUtility + .isTrue(properties + .getProperty(PropertyRegistry.TYPE_RESOLVER_FORCE_BIG_DECIMALS)); + } + + public FullyQualifiedJavaType calculateJavaType( + IntrospectedColumn introspectedColumn) { + FullyQualifiedJavaType answer; + JdbcTypeInformation jdbcTypeInformation = typeMap + .get(introspectedColumn.getJdbcType()); + + if (jdbcTypeInformation == null) { + switch (introspectedColumn.getJdbcType()) { + case Types.DECIMAL: + case Types.NUMERIC: + if (introspectedColumn.getScale() > 0 + || introspectedColumn.getLength() > 18 + || forceBigDecimals) { + answer = new FullyQualifiedJavaType(BigDecimal.class + .getName()); + } else if (introspectedColumn.getLength() > 9) { + answer = new FullyQualifiedJavaType(Long.class.getName()); + } else if (introspectedColumn.getLength() > 4) { + answer = new FullyQualifiedJavaType(Integer.class.getName()); + } else { + answer = new FullyQualifiedJavaType(Short.class.getName()); + } + break; + + default: + answer = null; + break; + } + } else { + answer = jdbcTypeInformation.getFullyQualifiedJavaType(); + } + + return answer; + } + + public String calculateJdbcTypeName(IntrospectedColumn introspectedColumn) { + String answer; + JdbcTypeInformation jdbcTypeInformation = typeMap + .get(introspectedColumn.getJdbcType()); + + if (jdbcTypeInformation == null) { + switch (introspectedColumn.getJdbcType()) { + case Types.DECIMAL: + answer = "DECIMAL"; //$NON-NLS-1$ + break; + case Types.NUMERIC: + answer = "NUMERIC"; //$NON-NLS-1$ + break; + default: + answer = null; + break; + } + } else { + answer = jdbcTypeInformation.getJdbcTypeName(); + } + + return answer; + } + + public void setWarnings(List warnings) { + this.warnings = warnings; + } + + public void setContext(Context context) { + this.context = context; + } + + public static class JdbcTypeInformation { + private String jdbcTypeName; + + private FullyQualifiedJavaType fullyQualifiedJavaType; + + public JdbcTypeInformation(String jdbcTypeName, + FullyQualifiedJavaType fullyQualifiedJavaType) { + this.jdbcTypeName = jdbcTypeName; + this.fullyQualifiedJavaType = fullyQualifiedJavaType; + } + + public String getJdbcTypeName() { + return jdbcTypeName; + } + + public FullyQualifiedJavaType getFullyQualifiedJavaType() { + return fullyQualifiedJavaType; + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/Jdbc4Types.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/Jdbc4Types.java new file mode 100644 index 0000000..e9ddf86 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/Jdbc4Types.java @@ -0,0 +1,10 @@ +package org.mybatis.generator.internal.types; + +public class Jdbc4Types { + // these are added manually until we move to JDK 6 + // TODO - remove after JDK 6 and use the java.sql.Types constants instead + public static final int LONGNVARCHAR = -16; + public static final int NVARCHAR = -9; + public static final int NCHAR = -15; + public static final int NCLOB = 2011; +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JdbcTypeNameTranslator.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JdbcTypeNameTranslator.java new file mode 100644 index 0000000..d27152e --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/types/JdbcTypeNameTranslator.java @@ -0,0 +1,146 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.types; + +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +/** + * TODO - Delete Me + * + * @author Jeff Butler + */ +public class JdbcTypeNameTranslator { + + private static Map typeToName; + private static Map nameToType; + + static { + typeToName = new HashMap(); + typeToName.put(Types.ARRAY, "ARRAY"); //$NON-NLS-1$ + typeToName.put(Types.BIGINT, "BIGINT"); //$NON-NLS-1$ + typeToName.put(Types.BINARY, "BINARY"); //$NON-NLS-1$ + typeToName.put(Types.BIT, "BIT"); //$NON-NLS-1$ + typeToName.put(Types.BLOB, "BLOB"); //$NON-NLS-1$ + typeToName.put(Types.BOOLEAN, "BOOLEAN"); //$NON-NLS-1$ + typeToName.put(Types.CHAR, "CHAR"); //$NON-NLS-1$ + typeToName.put(Types.CLOB, "CLOB"); //$NON-NLS-1$ + typeToName.put(Types.DATALINK, "DATALINK"); //$NON-NLS-1$ + typeToName.put(Types.DATE, "DATE"); //$NON-NLS-1$ + typeToName.put(Types.DECIMAL, "DECIMAL"); //$NON-NLS-1$ + typeToName.put(Types.DISTINCT, "DISTINCT"); //$NON-NLS-1$ + typeToName.put(Types.DOUBLE, "DOUBLE"); //$NON-NLS-1$ + typeToName.put(Types.FLOAT, "FLOAT"); //$NON-NLS-1$ + typeToName.put(Types.INTEGER, "INTEGER"); //$NON-NLS-1$ + typeToName.put(Types.JAVA_OBJECT, "JAVA_OBJECT"); //$NON-NLS-1$ + typeToName.put(Types.LONGVARBINARY, "LONGVARBINARY"); //$NON-NLS-1$ + typeToName.put(Types.LONGVARCHAR, "LONGVARCHAR"); //$NON-NLS-1$ + typeToName.put(Jdbc4Types.NCHAR, "NCHAR"); //$NON-NLS-1$ + typeToName.put(Jdbc4Types.NCLOB, "NCLOB"); //$NON-NLS-1$ + typeToName.put(Jdbc4Types.NVARCHAR, "NVARCHAR"); //$NON-NLS-1$ + typeToName.put(Jdbc4Types.LONGNVARCHAR, "LONGNVARCHAR"); //$NON-NLS-1$ + typeToName.put(Types.NULL, "NULL"); //$NON-NLS-1$ + typeToName.put(Types.NUMERIC, "NUMERIC"); //$NON-NLS-1$ + typeToName.put(Types.OTHER, "OTHER"); //$NON-NLS-1$ + typeToName.put(Types.REAL, "REAL"); //$NON-NLS-1$ + typeToName.put(Types.REF, "REF"); //$NON-NLS-1$ + typeToName.put(Types.SMALLINT, "SMALLINT"); //$NON-NLS-1$ + typeToName.put(Types.STRUCT, "STRUCT"); //$NON-NLS-1$ + typeToName.put(Types.TIME, "TIME"); //$NON-NLS-1$ + typeToName.put(Types.TIMESTAMP, "TIMESTAMP"); //$NON-NLS-1$ + typeToName.put(Types.TINYINT, "TINYINT"); //$NON-NLS-1$ + typeToName.put(Types.VARBINARY, "VARBINARY"); //$NON-NLS-1$ + typeToName.put(Types.VARCHAR, "VARCHAR"); //$NON-NLS-1$ + + nameToType = new HashMap(); + nameToType.put("ARRAY", Types.ARRAY); //$NON-NLS-1$ + nameToType.put("BIGINT", Types.BIGINT); //$NON-NLS-1$ + nameToType.put("BINARY", Types.BINARY); //$NON-NLS-1$ + nameToType.put("BIT", Types.BIT); //$NON-NLS-1$ + nameToType.put("BLOB", Types.BLOB); //$NON-NLS-1$ + nameToType.put("BOOLEAN", Types.BOOLEAN); //$NON-NLS-1$ + nameToType.put("CHAR", Types.CHAR); //$NON-NLS-1$ + nameToType.put("CLOB", Types.CLOB); //$NON-NLS-1$ + nameToType.put("DATALINK", Types.DATALINK); //$NON-NLS-1$ + nameToType.put("DATE", Types.DATE); //$NON-NLS-1$ + nameToType.put("DECIMAL", Types.DECIMAL); //$NON-NLS-1$ + nameToType.put("DISTINCT", Types.DISTINCT); //$NON-NLS-1$ + nameToType.put("DOUBLE", Types.DOUBLE); //$NON-NLS-1$ + nameToType.put("FLOAT", Types.FLOAT); //$NON-NLS-1$ + nameToType.put("INTEGER", Types.INTEGER); //$NON-NLS-1$ + nameToType.put("JAVA_OBJECT", Types.JAVA_OBJECT); //$NON-NLS-1$ + nameToType.put("LONGVARBINARY", Types.LONGVARBINARY); //$NON-NLS-1$ + nameToType.put("LONGVARCHAR", Types.LONGVARCHAR); //$NON-NLS-1$ + nameToType.put("NCHAR", Jdbc4Types.NCHAR); //$NON-NLS-1$ + nameToType.put("NCLOB", Jdbc4Types.NCLOB); //$NON-NLS-1$ + nameToType.put("NVARCHAR", Jdbc4Types.NVARCHAR); //$NON-NLS-1$ + nameToType.put("LONGNVARCHAR", Jdbc4Types.LONGNVARCHAR); //$NON-NLS-1$ + nameToType.put("NULL", Types.NULL); //$NON-NLS-1$ + nameToType.put("NUMERIC", Types.NUMERIC); //$NON-NLS-1$ + nameToType.put("OTHER", Types.OTHER); //$NON-NLS-1$ + nameToType.put("REAL", Types.REAL); //$NON-NLS-1$ + nameToType.put("REF", Types.REF); //$NON-NLS-1$ + nameToType.put("SMALLINT", Types.SMALLINT); //$NON-NLS-1$ + nameToType.put("STRUCT", Types.STRUCT); //$NON-NLS-1$ + nameToType.put("TIME", Types.TIME); //$NON-NLS-1$ + nameToType.put("TIMESTAMP", Types.TIMESTAMP); //$NON-NLS-1$ + nameToType.put("TINYINT", Types.TINYINT); //$NON-NLS-1$ + nameToType.put("VARBINARY", Types.VARBINARY); //$NON-NLS-1$ + nameToType.put("VARCHAR", Types.VARCHAR); //$NON-NLS-1$ + } + + /** + * Utility Class - no instances + */ + private JdbcTypeNameTranslator() { + super(); + } + + /** + * Translates from a java.sql.Types values to the proper iBATIS string + * representation of the type. + * + * @param jdbcType + * a value from java.sql.Types + * @return the iBATIS String representation of a JDBC type + */ + public static String getJdbcTypeName(int jdbcType) { + String answer = typeToName.get(jdbcType); + if (answer == null) { + answer = "OTHER"; //$NON-NLS-1$ + } + + return answer; + } + + /** + * Translates from the string representation of the type to the + * java.sql.Types value. + * + * @param jdbcTypeName + * the iBATIS String representation of a JDBC type + * @return a value from java.sql.Types + */ + public static int getJdbcType(String jdbcTypeName) { + Integer answer = nameToType.get(jdbcTypeName); + if (answer == null) { + answer = Types.OTHER; + } + + return answer; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/ClassloaderUtility.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/ClassloaderUtility.java new file mode 100644 index 0000000..db66f7a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/ClassloaderUtility.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.internal.util; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +/** + * This class holds methods useful for constructing custom classloaders. + * + * @author Jeff Butler + * + */ +public class ClassloaderUtility { + + /** + * Utility Class - No Instances + */ + private ClassloaderUtility() { + } + + public static ClassLoader getCustomClassloader(List entries) { + List urls = new ArrayList(); + File file; + + if (entries != null) { + for (String classPathEntry : entries) { + file = new File(classPathEntry); + if (!file.exists()) { + throw new RuntimeException(getString( + "RuntimeError.9", classPathEntry)); //$NON-NLS-1$ + } + + try { + urls.add(file.toURI().toURL()); + } catch (MalformedURLException e) { + // this shouldn't happen, but just in case... + throw new RuntimeException(getString( + "RuntimeError.9", classPathEntry)); //$NON-NLS-1$ + } + } + } + + ClassLoader parent = Thread.currentThread().getContextClassLoader(); + + URLClassLoader ucl = new URLClassLoader(urls.toArray(new URL[urls + .size()]), parent); + + return ucl; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/EqualsUtil.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/EqualsUtil.java new file mode 100644 index 0000000..0215a3d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/EqualsUtil.java @@ -0,0 +1,65 @@ +package org.mybatis.generator.internal.util; + +/** + * This class is from javapractices.com: + * + * http://www.javapractices.com/Topic17.cjp + * + * Collected methods which allow easy implementation of equals. + * + * Example use case in a class called Car: + * + *
+ * public boolean equals(Object that) {
+ *     if (this == that)
+ *         return true;
+ *     if (!(that instanceof Car))
+ *         return false;
+ *     Car thatCar = (Car) that;
+ *     return EqualsUtil.areEqual(this.fName, that.fName)
+ *             && EqualsUtil.areEqual(this.fNumDoors, that.fNumDoors)
+ *             && EqualsUtil.areEqual(this.fGasMileage, that.fGasMileage)
+ *             && EqualsUtil.areEqual(this.fColor, that.fColor)
+ *             && Arrays.equals(this.fMaintenanceChecks, that.fMaintenanceChecks); //array!
+ * }
+ * 
+ * + * Arrays are not handled by this class. This is because the + * Arrays.equals methods should be used for array fields. + */ +public final class EqualsUtil { + + static public boolean areEqual(boolean aThis, boolean aThat) { + return aThis == aThat; + } + + static public boolean areEqual(char aThis, char aThat) { + return aThis == aThat; + } + + static public boolean areEqual(long aThis, long aThat) { + /* + * Implementation Note Note that byte, short, and int are handled by + * this method, through implicit conversion. + */ + return aThis == aThat; + } + + static public boolean areEqual(float aThis, float aThat) { + return Float.floatToIntBits(aThis) == Float.floatToIntBits(aThat); + } + + static public boolean areEqual(double aThis, double aThat) { + return Double.doubleToLongBits(aThis) == Double.doubleToLongBits(aThat); + } + + /** + * Possibly-null object field. + * + * Includes type-safe enumerations and collections, but does not include + * arrays. See class comment. + */ + static public boolean areEqual(Object aThis, Object aThat) { + return aThis == null ? aThat == null : aThis.equals(aThat); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/HashCodeUtil.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/HashCodeUtil.java new file mode 100644 index 0000000..6669a2d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/HashCodeUtil.java @@ -0,0 +1,114 @@ +package org.mybatis.generator.internal.util; + +import java.lang.reflect.Array; + +/** + * This class is from javapractices.com: + * + * http://www.javapractices.com/Topic28.cjp + * + * Collected methods which allow easy implementation of hashCode. + * + * Example use case: + * + *
+ * public int hashCode() {
+ *     int result = HashCodeUtil.SEED;
+ *     //collect the contributions of various fields
+ *     result = HashCodeUtil.hash(result, fPrimitive);
+ *     result = HashCodeUtil.hash(result, fObject);
+ *     result = HashCodeUtil.hash(result, fArray);
+ *     return result;
+ * }
+ * 
+ */ +public final class HashCodeUtil { + + /** + * An initial value for a hashCode, to which is added + * contributions from fields. Using a non-zero value decreases collisons of + * hashCode values. + */ + public static final int SEED = 23; + + /** + * booleans. + */ + public static int hash(int aSeed, boolean aBoolean) { + return firstTerm(aSeed) + (aBoolean ? 1 : 0); + } + + /** + * chars. + */ + public static int hash(int aSeed, char aChar) { + return firstTerm(aSeed) + aChar; + } + + /** + * ints. + */ + public static int hash(int aSeed, int aInt) { + /* + * Implementation Note Note that byte and short are handled by this + * method, through implicit conversion. + */ + return firstTerm(aSeed) + aInt; + } + + /** + * longs. + */ + public static int hash(int aSeed, long aLong) { + return firstTerm(aSeed) + (int) (aLong ^ (aLong >>> 32)); + } + + /** + * floats. + */ + public static int hash(int aSeed, float aFloat) { + return hash(aSeed, Float.floatToIntBits(aFloat)); + } + + /** + * doubles. + */ + public static int hash(int aSeed, double aDouble) { + return hash(aSeed, Double.doubleToLongBits(aDouble)); + } + + /** + * aObject is a possibly-null object field, and possibly an + * array. + * + * If aObject is an array, then each element may be a primitive + * or a possibly-null object. + */ + public static int hash(int aSeed, Object aObject) { + int result = aSeed; + if (aObject == null) { + result = hash(result, 0); + } else if (!isArray(aObject)) { + result = hash(result, aObject.hashCode()); + } else { + int length = Array.getLength(aObject); + for (int idx = 0; idx < length; ++idx) { + Object item = Array.get(aObject, idx); + // recursive call! + result = hash(result, item); + } + } + return result; + } + + // / PRIVATE /// + private static final int fODD_PRIME_NUMBER = 37; + + private static int firstTerm(int aSeed) { + return fODD_PRIME_NUMBER * aSeed; + } + + private static boolean isArray(Object aObject) { + return aObject.getClass().isArray(); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/JavaBeansUtil.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/JavaBeansUtil.java new file mode 100644 index 0000000..5c73b14 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/JavaBeansUtil.java @@ -0,0 +1,166 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.util; + +import java.util.Locale; + +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; + +/** + * @author Jeff Butler + */ +public class JavaBeansUtil { + + /** + * + */ + private JavaBeansUtil() { + super(); + } + + /** + * JavaBeans rules: + * + * eMail > geteMail() firstName > getFirstName() URL > getURL() XAxis > + * getXAxis() a > getA() B > invalid - this method assumes that this is not + * the case. Call getValidPropertyName first. Yaxis > invalid - this method + * assumes that this is not the case. Call getValidPropertyName first. + * + * @param property + * @return the getter method name + */ + public static String getGetterMethodName(String property, + FullyQualifiedJavaType fullyQualifiedJavaType) { + StringBuilder sb = new StringBuilder(); + + sb.append(property); + if (Character.isLowerCase(sb.charAt(0))) { + if (sb.length() == 1 || !Character.isUpperCase(sb.charAt(1))) { + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + } + } + + if (fullyQualifiedJavaType.equals(FullyQualifiedJavaType + .getBooleanPrimitiveInstance())) { + sb.insert(0, "is"); //$NON-NLS-1$ + } else { + sb.insert(0, "get"); //$NON-NLS-1$ + } + + return sb.toString(); + } + + /** + * JavaBeans rules: + * + * eMail > seteMail() firstName > setFirstName() URL > setURL() XAxis > + * setXAxis() a > setA() B > invalid - this method assumes that this is not + * the case. Call getValidPropertyName first. Yaxis > invalid - this method + * assumes that this is not the case. Call getValidPropertyName first. + * + * @param property + * @return the setter method name + */ + public static String getSetterMethodName(String property) { + StringBuilder sb = new StringBuilder(); + + sb.append(property); + if (Character.isLowerCase(sb.charAt(0))) { + if (sb.length() == 1 || !Character.isUpperCase(sb.charAt(1))) { + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + } + } + + sb.insert(0, "set"); //$NON-NLS-1$ + + return sb.toString(); + } + + public static String getCamelCaseString(String inputString, + boolean firstCharacterUppercase) { + StringBuilder sb = new StringBuilder(); + + boolean nextUpperCase = false; + for (int i = 0; i < inputString.length(); i++) { + char c = inputString.charAt(i); + + switch (c) { + case '_': + case '-': + case '@': + case '$': + case '#': + case ' ': + case '/': + case '&': + if (sb.length() > 0) { + nextUpperCase = true; + } + break; + + default: + if (nextUpperCase) { + sb.append(Character.toUpperCase(c)); + nextUpperCase = false; + } else { + sb.append(Character.toLowerCase(c)); + } + break; + } + } + + if (firstCharacterUppercase) { + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + } + + return sb.toString(); + } + + /** + * This method ensures that the specified input string is a valid Java + * property name. The rules are as follows: + * + * 1. If the first character is lower case, then OK 2. If the first two + * characters are upper case, then OK 3. If the first character is upper + * case, and the second character is lower case, then the first character + * should be made lower case + * + * eMail > eMail firstName > firstName URL > URL XAxis > XAxis a > a B > b + * Yaxis > yaxis + * + * @param inputString + * @return the valid property name + */ + public static String getValidPropertyName(String inputString) { + String answer; + + if (inputString == null) { + answer = null; + } else if (inputString.length() < 2) { + answer = inputString.toLowerCase(Locale.US); + } else { + if (Character.isUpperCase(inputString.charAt(0)) + && !Character.isUpperCase(inputString.charAt(1))) { + answer = inputString.substring(0, 1).toLowerCase(Locale.US) + + inputString.substring(1); + } else { + answer = inputString; + } + } + + return answer; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/StringUtility.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/StringUtility.java new file mode 100644 index 0000000..e11a734 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/StringUtility.java @@ -0,0 +1,105 @@ +/* + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.util; + +import java.util.StringTokenizer; + +/** + * + * @author Jeff Butler + */ +public class StringUtility { + + /** + * Utility class. No instances allowed + */ + private StringUtility() { + super(); + } + + public static boolean stringHasValue(String s) { + return s != null && s.length() > 0; + } + + public static String composeFullyQualifiedTableName(String catalog, + String schema, String tableName, char separator) { + StringBuilder sb = new StringBuilder(); + + if (stringHasValue(catalog)) { + sb.append(catalog); + sb.append(separator); + } + + if (stringHasValue(schema)) { + sb.append(schema); + sb.append(separator); + } else { + if (sb.length() > 0) { + sb.append(separator); + } + } + + sb.append(tableName); + + return sb.toString(); + } + + public static boolean stringContainsSpace(String s) { + return s != null && s.indexOf(' ') != -1; + } + + public static String escapeStringForJava(String s) { + StringTokenizer st = new StringTokenizer(s, "\"", true); //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("\"".equals(token)) { //$NON-NLS-1$ + sb.append("\\\""); //$NON-NLS-1$ + } else { + sb.append(token); + } + } + + return sb.toString(); + } + + public static String escapeStringForXml(String s) { + StringTokenizer st = new StringTokenizer(s, "\"", true); //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("\"".equals(token)) { //$NON-NLS-1$ + sb.append("""); //$NON-NLS-1$ + } else { + sb.append(token); + } + } + + return sb.toString(); + } + + public static boolean isTrue(String s) { + return "true".equalsIgnoreCase(s); //$NON-NLS-1$ + } + + public static boolean stringContainsSQLWildcard(String s) { + if (s == null) { + return false; + } + + return s.indexOf('%') != -1 || s.indexOf('_') != -1; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/Messages.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/Messages.java new file mode 100644 index 0000000..f381555 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/Messages.java @@ -0,0 +1,69 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.internal.util.messages; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @author Jeff Butler + */ +public class Messages { + private static final String BUNDLE_NAME = "org.mybatis.generator.internal.util.messages.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getString(String key, String parm1) { + try { + return MessageFormat.format(RESOURCE_BUNDLE.getString(key), + new Object[] { parm1 }); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getString(String key, String parm1, String parm2) { + try { + return MessageFormat.format(RESOURCE_BUNDLE.getString(key), + new Object[] { parm1, parm2 }); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getString(String key, String parm1, String parm2, + String parm3) { + try { + return MessageFormat.format(RESOURCE_BUNDLE.getString(key), + new Object[] { parm1, parm2, parm3 }); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/messages.properties b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/messages.properties new file mode 100644 index 0000000..d4de8ee --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/internal/util/messages/messages.properties @@ -0,0 +1,128 @@ +ValidationError.0=JavaModelGenerator Target Project is Required for context {0} +ValidationError.1=SQLMapGenerator Target Project is Required for context {0} +ValidationError.2=DAOGenerator Target Project is Required for context {0} +ValidationError.3=No Tables Specified for context {0} +ValidationError.4=JDBC Driver Class Must Be Specified +ValidationError.5=JDBC Connection URL Must Be Specified +ValidationError.6=Missing table name in table configuration at index {0} +ValidationError.7=SQL Statement is required if a generated key is specified in table configuration for table {0} +ValidationError.8=JavaModelGeneratorConfiguration is required for context {0} +ValidationError.9=SqlMapGeneratorConfiguration is required for context {0} +ValidationError.10=JdbcConnectionConfiguration is required for context {0} +ValidationError.11=At least one configuration element is required +ValidationError.12={0} Target Package is Required for context {1} +ValidationError.13=If "useColumnIndexes" property is set, then either both or neither query id must be set for table {0} +ValidationError.14="searchString" is required for ColumnRenamingRule in table {0} +ValidationError.15=Generated key type must be either "pre" or "post" if the type is specified for a generated key for table {0} +ValidationError.16="id" is required in a context +ValidationError.17="type" is required in a plugin in context {0} +ValidationError.18={0} requires the {1} property +ValidationError.19=A null or empty string is not allowed for a classpath entry +ValidationError.20="type" is required for DAO Generator in context {0} +ValidationError.21="column" is required for in table {0} +ValidationError.22="column" is required for in table {0} +ValidationError.23=Generated key in table {0} cannot be both "pre" and identity +ValidationError.24=Generated key in table {0} cannot be both "post" and not identity +ValidationError.25=targetRuntime in context {0} is invalid + +RuntimeError.0=configfile is a required parameter +RuntimeError.1=configfile {0} does not exist +RuntimeError.2=Configuration is required +RuntimeError.3=Cannot generate unique file name in directory {0} +RuntimeError.4=XML Parser Error on line {0}: {1} +RuntimeError.5=This is not a MyBatis Generator Configuration File +RuntimeError.6=Cannot instantiate object of type {0} +RuntimeError.7=Cannot connect to database (possibly bad driver/URL combination) +RuntimeError.8=Exception getting JDBC Driver +RuntimeError.9=Cannot resolve classpath entry: {0} +RuntimeError.11=Enumerations do not have super classes +RuntimeError.12=Internal Error - Cannot calculate record type for selectByExample method +RuntimeError.13=Invalid model type: {0} +RuntimeError.14=Either resource or URL is required on the element, but not both +RuntimeError.15= resource {0} does not exist +RuntimeError.16=Cannot load properties from resource {0} +RuntimeError.17=Cannot load properties from url {0} +RuntimeError.18=Unsupported XML Node Type {0} in XML File Merger +RuntimeError.19=Value missing after {0} +RuntimeError.20=Unknown argument: {0} +RuntimeError.21=Error creating logger for class {0}. Cause: {1} +RuntimeError.22=Invalid Type Specification: {0}. + +Warning.0=There are no statements enabled for table {0}, this table will be ignored. +Warning.1=Table {0} does not exist, this table will be ignored +Warning.2=Existing file not overwritten, the generated file is saved as {0} +Warning.3=Column {0}, specified for override in table {1}, does not exist in the table. +Warning.4=Column {0}, specified to be ignored in table {1}, does not exist in the table. +Warning.5=Column {0}, specified as an identity column in table {1}, does not exist in the table. +Warning.6=Column {0}, specified as a generated key column in table {1}, does not exist in the table. +Warning.7=XML Parser Warning on line {0}: {1} +Warning.9=The specified target project directory {0} does not exist +Warning.10=Cannot create directory {0} +Warning.11=Existing file {0} was overwritten +Warning.12=The existing XML file {0} is not the same format as the generated file. \ + The existing file will not be changed. +Warning.13=Exception while attempting to merge the XML file {0}. \ + The existing file will not be changed. +Warning.14=Unsupported Data Type {0} in table {1}, column: {2}, property defaults to Object type. +Warning.15=Cannot obtain primary key information from the database, generated objects may be incomplete +Warning.16=Invalid value for exampleMethodVisibility specified ({0}), defaulting to public +Warning.17=Cannot instantiate DAO method name calculator of type {0}, using default calculator +Warning.18=Table {0} contains only LOB fields, this table will be ignored +Warning.19=Table configuration with catalog {0}, schema {1}, and table {2} did not resolve to any tables +Warning.20=Root class {0} cannot be loaded, checking for member overrides is disabled for this class +Warning.21=Property {0} exists in root class {1}, but is not of type {2}. MyBatis Generator will generate the property. +Warning.22=Property {0} exists in root class {1}, but does not have a getter. MyBatis Generator will generate the property. +Warning.23=Property {0} exists in root class {1}, but does not have a setter. MyBatis Generator will generate the property. +Warning.24=Plugin {0} in context {1} is invalid and will be ignored. +Warning.25=Table Configuration {0} matched more than one table ({1}) + +Progress.0=Connecting to the Database +Progress.1=Introspecting table {0} +Progress.3=XML Parser Errors occurred: +Progress.4=MyBatis Generator finished successfully. +Progress.5=MyBatis Generator finished successfully, there were warnings. +Progress.6=Generating Example class for table {0} +Progress.7=Generating Primary Key class for table {0} +Progress.8=Generating Record class for table {0} +Progress.9=Generating Record class (with BLOBs) for table {0} +Progress.12=Generating SQL Map for table {0} +Progress.13=Found SQL Statement: {0} +Progress.14=Generating DAO Interface and Implementation for table {0} +Progress.15=Saving file {0} +Progress.16=Invalid configuration. Details follow... +Progress.17=Generating Mapper Interface for table {0} +Progress.18=Generating SQL Provider for table {0} + +Tracing.1=Retrieving column information for table "{0}" +Tracing.2=Found column "{0}", data type {1}, in table "{2}" +Tracing.3=Removing column "{0}" in table "{1}" because it is ignored by configuration +Tracing.4=Found override for column "{0}" in table "{1}" + +Usage.Lines=27 +Usage.0=MyBatis Generator - a code generator for MyBatis and iBATIS. Usage: +Usage.1=\ java -jar mybatis-generator-core-x.x.x.jar -configfile file_name +Usage.2=\ [-overwrite] [-contextids ids] [-tables tableNames] +Usage.3=\ [-forceJavaLogging] [-verbose] [-?|-h] +Usage.4= +Usage.5=Where: +Usage.6=\ -configfile: Specifies the name of the XML configuration file (required) +Usage.7= +Usage.8=\ -overwrite: If specified then existing Java files will be overwritten. +Usage.9=\ If not specified, then the generator will not overwrite +Usage.10=\ existing Java files (will save results in uniquely named files) +Usage.11= +Usage.12=\ -contextids: Used to specify a comma delimited list of contexts to use in +Usage.13=\ this invocation. If not specified, all contexts will be used. +Usage.14= +Usage.15=\ -tables: Used to specify a comma delimited list of tables to use in this +Usage.16=\ invocation. If not specified, all tables will be used. Table +Usage.17=\ names must be fully qualified (e.g. schema.tablename). Table names +Usage.18=\ must exactly match the case specified in the configuration file. +Usage.19= +Usage.20=\ -forceJavaLogging: Force the use of standard Java logging even if Log4J is +Usage.21=\ is available in the runtime classpath. If not specified, +Usage.22=\ Log4J will be used if it is available at runtime. +Usage.23= +Usage.24=\ -verbose: If specified, write progress messages to the console. +Usage.25= +Usage.26=\ -?|-h: Display this help text and exit. diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/AbstractLogFactory.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/AbstractLogFactory.java new file mode 100644 index 0000000..c298f30 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/AbstractLogFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.logging; + +/** + * Defines the interface for creating Log implementations. + * + * @author Jeff Butler + * + */ +public interface AbstractLogFactory { + Log getLog(Class aClass); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/JdkLoggingImpl.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/JdkLoggingImpl.java new file mode 100644 index 0000000..361981d --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/JdkLoggingImpl.java @@ -0,0 +1,68 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.logging; + +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +/** + * + * @author Clinton Begin + * @author Jeff Butler + * + */ +public class JdkLoggingImpl implements Log { + + private Logger log; + + public JdkLoggingImpl(Class clazz) { + log = Logger.getLogger(clazz.getName()); + } + + public boolean isDebugEnabled() { + return log.isLoggable(Level.FINE); + } + + public void error(String s, Throwable e) { + LogRecord lr = new LogRecord(Level.SEVERE, s); + lr.setSourceClassName(log.getName()); + lr.setThrown(e); + + log.log(lr); + } + + public void error(String s) { + LogRecord lr = new LogRecord(Level.SEVERE, s); + lr.setSourceClassName(log.getName()); + + log.log(lr); + } + + public void debug(String s) { + LogRecord lr = new LogRecord(Level.FINE, s); + lr.setSourceClassName(log.getName()); + + log.log(lr); + } + + public void warn(String s) { + LogRecord lr = new LogRecord(Level.WARNING, s); + lr.setSourceClassName(log.getName()); + + log.log(lr); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log.java new file mode 100644 index 0000000..630eb4f --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log.java @@ -0,0 +1,33 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.logging; + +/** + * + * @author Clinton Begin + */ +public interface Log { + + boolean isDebugEnabled(); + + void error(String s, Throwable e); + + void error(String s); + + public void debug(String s); + + public void warn(String s); +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log4jImpl.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log4jImpl.java new file mode 100644 index 0000000..013d36a --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/Log4jImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.logging; + +import org.apache.log4j.Logger; + +/** + * + * @author Clinton Begin + * + */ +public class Log4jImpl implements Log { + + private Logger log; + + public Log4jImpl(Class clazz) { + log = Logger.getLogger(clazz); + } + + public boolean isDebugEnabled() { + return log.isDebugEnabled(); + } + + public void error(String s, Throwable e) { + log.error(s, e); + } + + public void error(String s) { + log.error(s); + } + + public void debug(String s) { + log.debug(s); + } + + public void warn(String s) { + log.warn(s); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/LogFactory.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/LogFactory.java new file mode 100644 index 0000000..70f1cb3 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/logging/LogFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.logging; + +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import org.mybatis.generator.internal.ObjectFactory; + +/** + * Factory for creating loggers. Uses runtime introspection to determine the + * AbstractLogFactory implementation. + * + * @author Jeff Butler + * + */ +public class LogFactory { + private static AbstractLogFactory logFactory; + + static { + try { + ObjectFactory.internalClassForName("org.apache.log4j.Logger"); //$NON-NLS-1$ + logFactory = new Log4jLoggingLogFactory(); + } catch (Exception e) { + logFactory = new JdkLoggingLogFactory(); + } + } + + public static Log getLog(Class clazz) { + try { + return logFactory.getLog(clazz); + } catch (Throwable t) { + throw new RuntimeException(getString("RuntimeError.21", //$NON-NLS-1$ + clazz.getName(), t.getMessage()), t); + } + } + + /** + * This method will switch the logging implementation to Java native + * logging. This is useful in situations where you want to use Java native + * logging to log activity but Log4J is on the classpath. Note that + * this method is only effective for log classes obtained after calling this + * method. If you intend to use this method you should call it before + * calling any other method. + */ + public static synchronized void forceJavaLogging() { + logFactory = new JdkLoggingLogFactory(); + } + + private static class JdkLoggingLogFactory implements AbstractLogFactory { + public Log getLog(Class clazz) { + return new JdkLoggingImpl(clazz); + } + } + + private static class Log4jLoggingLogFactory implements AbstractLogFactory { + public Log getLog(Class clazz) { + return new Log4jImpl(clazz); + } + } + + public static void setLogFactory(AbstractLogFactory logFactory) { + LogFactory.logFactory = logFactory; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/CaseInsensitiveLikePlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/CaseInsensitiveLikePlugin.java new file mode 100644 index 0000000..f19e9f6 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/CaseInsensitiveLikePlugin.java @@ -0,0 +1,109 @@ +/* + * Copyright 2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.plugins; + +import java.util.List; + +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.InnerClass; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.codegen.ibatis2.Ibatis2FormattingUtilities; + +/** + * This plugin demonstrates adding methods to the example class to enable + * case-insensitive LIKE searches. It shows hows to construct new methods and + * add them to an existing class. + * + * This plugin only adds methods for String fields mapped to a JDBC character + * type (CHAR, VARCHAR, etc.) + * + * @author Jeff Butler + * + */ +public class CaseInsensitiveLikePlugin extends PluginAdapter { + + /** + * + */ + public CaseInsensitiveLikePlugin() { + super(); + } + + public boolean validate(List warnings) { + return true; + } + + @Override + public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + + InnerClass criteria = null; + // first, find the Criteria inner class + for (InnerClass innerClass : topLevelClass.getInnerClasses()) { + if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$ + criteria = innerClass; + break; + } + } + + if (criteria == null) { + // can't find the inner class for some reason, bail out. + return true; + } + + for (IntrospectedColumn introspectedColumn : introspectedTable + .getNonBLOBColumns()) { + if (!introspectedColumn.isJdbcCharacterColumn() + || !introspectedColumn.isStringColumn()) { + continue; + } + + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.addParameter(new Parameter(introspectedColumn + .getFullyQualifiedJavaType(), "value")); //$NON-NLS-1$ + + StringBuilder sb = new StringBuilder(); + sb.append(introspectedColumn.getJavaProperty()); + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + sb.insert(0, "and"); //$NON-NLS-1$ + sb.append("LikeInsensitive"); //$NON-NLS-1$ + method.setName(sb.toString()); + method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance()); + + sb.setLength(0); + sb.append("addCriterion(\"upper("); //$NON-NLS-1$ + sb.append(Ibatis2FormattingUtilities + .getAliasedActualColumnName(introspectedColumn)); + sb.append(") like\", value.toUpperCase(), \""); //$NON-NLS-1$ + sb.append(introspectedColumn.getJavaProperty()); + sb.append("\");"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$ + + criteria.addMethod(method); + } + + return true; + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/EqualsHashCodePlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/EqualsHashCodePlugin.java new file mode 100644 index 0000000..eb250e1 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/EqualsHashCodePlugin.java @@ -0,0 +1,311 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.plugins; + +import static org.mybatis.generator.internal.util.JavaBeansUtil.getGetterMethodName; + +import java.util.Iterator; +import java.util.List; + +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.OutputUtilities; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.java.TopLevelClass; + +/** + * This plugin adds equals() and hashCode() methods to the generated model + * classes. It demonstrates the process of adding methods to generated classes + *

+ * The equals method generated by this class is correct in most cases, + * but will probably NOT be correct if you have specified a rootClass - because + * our equals method only checks the fields it knows about. + *

+ * Similarly, the hashCode method generated by this class only relies + * on fields it knows about. Anything you add, or fields in a super class will + * not be factored into the hash code. + * + * @author Jeff Butler + * + */ +public class EqualsHashCodePlugin extends PluginAdapter { + + public EqualsHashCodePlugin() { + } + + /** + * This plugin is always valid - no properties are required + */ + public boolean validate(List warnings) { + return true; + } + + @Override + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + List columns; + if (introspectedTable.getRules().generateRecordWithBLOBsClass()) { + columns = introspectedTable.getNonBLOBColumns(); + } else { + columns = introspectedTable.getAllColumns(); + } + + generateEquals(topLevelClass, columns, introspectedTable); + generateHashCode(topLevelClass, columns, introspectedTable); + + return true; + } + + @Override + public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + generateEquals(topLevelClass, introspectedTable.getPrimaryKeyColumns(), + introspectedTable); + generateHashCode(topLevelClass, introspectedTable + .getPrimaryKeyColumns(), introspectedTable); + + return true; + } + + @Override + public boolean modelRecordWithBLOBsClassGenerated( + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + generateEquals(topLevelClass, introspectedTable.getAllColumns(), + introspectedTable); + generateHashCode(topLevelClass, introspectedTable.getAllColumns(), + introspectedTable); + + return true; + } + + /** + * Generates an equals method that does a comparison of all fields. + *

+ * The generated equals method will be correct unless: + *

    + *
  • Other fields have been added to the generated classes
  • + *
  • A rootClass is specified that holds state
  • + *
+ * + * @param topLevelClass + * the class to which the method will be added + * @param introspectedColumns + * column definitions of this class and any superclass of this + * class + * @param introspectedTable + * the table corresponding to this class + */ + protected void generateEquals(TopLevelClass topLevelClass, + List introspectedColumns, + IntrospectedTable introspectedTable) { + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setReturnType(FullyQualifiedJavaType + .getBooleanPrimitiveInstance()); + method.setName("equals"); //$NON-NLS-1$ + method.addParameter(new Parameter(FullyQualifiedJavaType + .getObjectInstance(), "that")); //$NON-NLS-1$ + if (introspectedTable.isJava5Targeted()) { + method.addAnnotation("@Override"); //$NON-NLS-1$ + } + + context.getCommentGenerator().addGeneralMethodComment(method, + introspectedTable); + + method.addBodyLine("if (this == that) {"); //$NON-NLS-1$ + method.addBodyLine("return true;"); //$NON-NLS-1$ + method.addBodyLine("}"); //$NON-NLS-1$ + + method.addBodyLine("if (that == null) {"); //$NON-NLS-1$ + method.addBodyLine("return false;"); //$NON-NLS-1$ + method.addBodyLine("}"); //$NON-NLS-1$ + + method.addBodyLine("if (getClass() != that.getClass()) {"); //$NON-NLS-1$ + method.addBodyLine("return false;"); //$NON-NLS-1$ + method.addBodyLine("}"); //$NON-NLS-1$ + + StringBuilder sb = new StringBuilder(); + sb.append(topLevelClass.getType().getShortName()); + sb.append(" other = ("); //$NON-NLS-1$ + sb.append(topLevelClass.getType().getShortName()); + sb.append(") that;"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + + boolean first = true; + Iterator iter = introspectedColumns.iterator(); + while (iter.hasNext()) { + IntrospectedColumn introspectedColumn = iter.next(); + + sb.setLength(0); + + if (first) { + sb.append("return ("); //$NON-NLS-1$ + first = false; + } else { + OutputUtilities.javaIndent(sb, 1); + sb.append("&& ("); //$NON-NLS-1$ + } + + String getterMethod = getGetterMethodName( + introspectedColumn.getJavaProperty(), introspectedColumn + .getFullyQualifiedJavaType()); + + if (introspectedColumn.getFullyQualifiedJavaType().isPrimitive()) { + sb.append("this."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() == "); //$NON-NLS-1$ + sb.append("other."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("())"); //$NON-NLS-1$ + } else { + sb.append("this."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() == null ? other."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() == null : this."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("().equals(other."); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("()))"); //$NON-NLS-1$ + } + + if (!iter.hasNext()) { + sb.append(';'); + } + + method.addBodyLine(sb.toString()); + } + + topLevelClass.addMethod(method); + } + + /** + * Generates a hashCode method that includes all fields. + *

+ * Note that this implementation is based on the eclipse foundation hashCode + * generator. + * + * @param topLevelClass + * the class to which the method will be added + * @param introspectedColumns + * column definitions of this class and any superclass of this + * class + * @param introspectedTable + * the table corresponding to this class + */ + protected void generateHashCode(TopLevelClass topLevelClass, + List introspectedColumns, + IntrospectedTable introspectedTable) { + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setReturnType(FullyQualifiedJavaType.getIntInstance()); + method.setName("hashCode"); //$NON-NLS-1$ + if (introspectedTable.isJava5Targeted()) { + method.addAnnotation("@Override"); //$NON-NLS-1$ + } + + context.getCommentGenerator().addGeneralMethodComment(method, + introspectedTable); + + method.addBodyLine("final int prime = 31;"); //$NON-NLS-1$ + method.addBodyLine("int result = 1;"); //$NON-NLS-1$ + + StringBuilder sb = new StringBuilder(); + boolean hasTemp = false; + Iterator iter = introspectedColumns.iterator(); + while (iter.hasNext()) { + IntrospectedColumn introspectedColumn = iter.next(); + + FullyQualifiedJavaType fqjt = introspectedColumn + .getFullyQualifiedJavaType(); + + String getterMethod = getGetterMethodName( + introspectedColumn.getJavaProperty(), fqjt); + + sb.setLength(0); + if (fqjt.isPrimitive()) { + if ("boolean".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + ("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() ? 1231 : 1237);"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("byte".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + "); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("();"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("char".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + "); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("();"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("double".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + if (!hasTemp) { + method.addBodyLine("long temp;"); //$NON-NLS-1$ + hasTemp = true; + } + sb.append("temp = Double.doubleToLongBits("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("());"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + method + .addBodyLine("result = prime * result + (int) (temp ^ (temp >>> 32));"); //$NON-NLS-1$ + } else if ("float".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb + .append("result = prime * result + Float.floatToIntBits("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("());"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("int".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + "); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("();"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("long".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + (int) ("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() ^ ("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() >>> 32));"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else if ("short".equals(fqjt.getFullyQualifiedName())) { //$NON-NLS-1$ + sb.append("result = prime * result + "); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("();"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } else { + // should never happen + continue; + } + } else { + sb.append("result = prime * result + (("); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("() == null) ? 0 : "); //$NON-NLS-1$ + sb.append(getterMethod); + sb.append("().hashCode());"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } + } + + method.addBodyLine("return result;"); //$NON-NLS-1$ + + topLevelClass.addMethod(method); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/RenameExampleClassPlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/RenameExampleClassPlugin.java new file mode 100644 index 0000000..b41dedc --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/RenameExampleClassPlugin.java @@ -0,0 +1,100 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mybatis.generator.plugins; + +import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; +import static org.mybatis.generator.internal.util.messages.Messages.getString; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.IntrospectedTable; + +/** + * This plugin demonstrates overriding the initialized() method to rename the + * generated example classes. Instead of xxxExample, the classes will be named + * xxxCriteria + * + * This plugin accepts two properties: + *

    + *
  • searchString (required) the regular expression of the name + * search.
  • + *
  • replaceString (required) the replacement String.
  • + *
+ * + * For example, to change the name of the generated Example classes from + * xxxExample to xxxCriteria, specify the following: + * + *
+ *
searchString
+ *
Example$
+ *
replaceString
+ *
Criteria
+ *
+ * + * + * @author Jeff Butler + * + */ +public class RenameExampleClassPlugin extends PluginAdapter { + private String searchString; + private String replaceString; + private Pattern pattern; + + /** + * + */ + public RenameExampleClassPlugin() { + } + + public boolean validate(List warnings) { + + searchString = properties.getProperty("searchString"); //$NON-NLS-1$ + replaceString = properties.getProperty("replaceString"); //$NON-NLS-1$ + + boolean valid = stringHasValue(searchString) + && stringHasValue(replaceString); + + if (valid) { + pattern = Pattern.compile(searchString); + } else { + if (!stringHasValue(searchString)) { + warnings.add(getString("ValidationError.18", //$NON-NLS-1$ + "RenameExampleClassPlugin", //$NON-NLS-1$ + "searchString")); //$NON-NLS-1$ + } + if (!stringHasValue(replaceString)) { + warnings.add(getString("ValidationError.18", //$NON-NLS-1$ + "RenameExampleClassPlugin", //$NON-NLS-1$ + "replaceString")); //$NON-NLS-1$ + } + } + + return valid; + } + + @Override + public void initialized(IntrospectedTable introspectedTable) { + String oldType = introspectedTable.getExampleType(); + Matcher matcher = pattern.matcher(oldType); + oldType = matcher.replaceAll(replaceString); + + introspectedTable.setExampleType(oldType); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/SerializablePlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/SerializablePlugin.java new file mode 100644 index 0000000..94a60ce --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/SerializablePlugin.java @@ -0,0 +1,110 @@ +/* + * Copyright 2008 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.plugins; + +import java.util.List; +import java.util.Properties; + +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.TopLevelClass; + +/** + * This plugin adds the java.io.Serializable marker interface to all generated + * model objects. + *

+ * This plugin demonstrates adding capabilities to generated Java artifacts, and + * shows the proper way to add imports to a compilation unit. + *

+ * Important: This is a simplistic implementation of serializable and does not + * attempt to do any versioning of classes. + * + * @author Jeff Butler + * + */ +public class SerializablePlugin extends PluginAdapter { + + private FullyQualifiedJavaType serializable; + private FullyQualifiedJavaType gwtSerializable; + private boolean addGWTInterface; + private boolean suppressJavaInterface; + + public SerializablePlugin() { + super(); + serializable = new FullyQualifiedJavaType("java.io.Serializable"); //$NON-NLS-1$ + gwtSerializable = new FullyQualifiedJavaType("com.google.gwt.user.client.rpc.IsSerializable"); //$NON-NLS-1$ + } + + public boolean validate(List warnings) { + // this plugin is always valid + return true; + } + + @Override + public void setProperties(Properties properties) { + super.setProperties(properties); + addGWTInterface = Boolean.valueOf(properties.getProperty("addGWTInterface")); //$NON-NLS-1$ + suppressJavaInterface = Boolean.valueOf(properties.getProperty("suppressJavaInterface")); //$NON-NLS-1$ + } + + @Override + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + makeSerializable(topLevelClass, introspectedTable); + return true; + } + + @Override + public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + makeSerializable(topLevelClass, introspectedTable); + return true; + } + + @Override + public boolean modelRecordWithBLOBsClassGenerated( + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + makeSerializable(topLevelClass, introspectedTable); + return true; + } + + protected void makeSerializable(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + if (addGWTInterface) { + topLevelClass.addImportedType(gwtSerializable); + topLevelClass.addSuperInterface(gwtSerializable); + } + + if (!suppressJavaInterface) { + topLevelClass.addImportedType(serializable); + topLevelClass.addSuperInterface(serializable); + + Field field = new Field(); + field.setFinal(true); + field.setInitializationString("1L"); //$NON-NLS-1$ + field.setName("serialVersionUID"); //$NON-NLS-1$ + field.setStatic(true); + field.setType(new FullyQualifiedJavaType("long")); //$NON-NLS-1$ + field.setVisibility(JavaVisibility.PRIVATE); + context.getCommentGenerator().addFieldComment(field, introspectedTable); + + topLevelClass.addField(field); + } + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/ToStringPlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/ToStringPlugin.java new file mode 100644 index 0000000..8b4f383 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/ToStringPlugin.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012 MyBatis.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.plugins; + +import java.util.List; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.TopLevelClass; + +public class ToStringPlugin extends PluginAdapter { + public boolean validate(List warnings) { + return true; + } + + @Override + public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + generateToString(introspectedTable, topLevelClass); + return true; + } + + @Override + public boolean modelRecordWithBLOBsClassGenerated( + TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { + generateToString(introspectedTable, topLevelClass); + return true; + } + + @Override + public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, + IntrospectedTable introspectedTable) { + generateToString(introspectedTable, topLevelClass); + return true; + } + + private void generateToString(IntrospectedTable introspectedTable, + TopLevelClass topLevelClass) { + Method method = new Method(); + method.setVisibility(JavaVisibility.PUBLIC); + method.setReturnType(FullyQualifiedJavaType.getStringInstance()); + method.setName("toString"); //$NON-NLS-1$ + if (introspectedTable.isJava5Targeted()) { + method.addAnnotation("@Override"); //$NON-NLS-1$ + } + + context.getCommentGenerator().addGeneralMethodComment(method, + introspectedTable); + + method.addBodyLine("StringBuilder sb = new StringBuilder();"); //$NON-NLS-1$ + method.addBodyLine("sb.append(getClass().getSimpleName());"); //$NON-NLS-1$ + method.addBodyLine("sb.append(\" [\");"); //$NON-NLS-1$ + method.addBodyLine("sb.append(\"Hash = \").append(hashCode());"); //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + for (Field field : topLevelClass.getFields()) { + String property = field.getName(); + sb.setLength(0); + sb.append("sb.append(\"").append(", ").append(property) //$NON-NLS-1$ //$NON-NLS-2$ + .append("=\")").append(".append(").append(property) //$NON-NLS-1$ //$NON-NLS-2$ + .append(");"); //$NON-NLS-1$ + method.addBodyLine(sb.toString()); + } + + method.addBodyLine("sb.append(\"]\");"); //$NON-NLS-1$ + method.addBodyLine("return sb.toString();"); //$NON-NLS-1$ + + topLevelClass.addMethod(method); + } +} diff --git a/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/VirtualPrimaryKeyPlugin.java b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/VirtualPrimaryKeyPlugin.java new file mode 100644 index 0000000..c2d9c32 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/java/org/mybatis/generator/plugins/VirtualPrimaryKeyPlugin.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012 The MyBatis Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mybatis.generator.plugins; + +import java.util.List; +import java.util.StringTokenizer; + +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.PluginAdapter; + +/** + * This plugin can be used to specify columns that act as a primary key, even if + * they are not strictly defined as primary keys in the database. + * + * To use the plugin, add a property to the table configuration specifying a + * comma delimited list of column names to use as a primary key: + * + * + * + * + * + * @author Jeff Butler + * + */ +public class VirtualPrimaryKeyPlugin extends PluginAdapter { + + public boolean validate(List warnings) { + return true; + } + + @Override + public void initialized(IntrospectedTable introspectedTable) { + String virtualKey = introspectedTable.getTableConfiguration() + .getProperty("virtualKeyColumns"); //$NON-NLS-1$ + + if (virtualKey != null) { + StringTokenizer st = new StringTokenizer(virtualKey, ", ", false); //$NON-NLS-1$ + while (st.hasMoreTokens()) { + String column = st.nextToken(); + introspectedTable.addPrimaryKeyColumn(column); + } + } + } +} diff --git a/coffice-toolbox-codegen/src/main/resources/generatorConfig.xml b/coffice-toolbox-codegen/src/main/resources/generatorConfig.xml new file mode 100644 index 0000000..fdfeef6 --- /dev/null +++ b/coffice-toolbox-codegen/src/main/resources/generatorConfig.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
\ No newline at end of file diff --git a/coffice-toolbox-codegen/src/main/resources/mybatis-generator-core-1.3.2-sources.jar b/coffice-toolbox-codegen/src/main/resources/mybatis-generator-core-1.3.2-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..8480f8cf01293bdd4b3c9d7d7aec6e399ab4767c GIT binary patch literal 411564 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�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≈NsW*Q zqt5Z6AS*dfxzQz9%G!XEFq=yK=DWunIsvTVG_gV^&+;fQd%6DCuXXQ7v-53Z>wX)W z?+)Wj_IF*zTf!RNFE6rfzhhqNCR3=-+H834rsj9to?7io_y#r%t&4rC`FMxF;lcGm z1NfkZOEJS~8NGYLC|(X!>aOKWDJ%3!f|g19|C&`1>lvQ`lkJ<>@~VrM-`DZvS~Xax z!0ceEsoFGmT|Rgb(8T-MQ}7#o0QT3t`!H_aD?Fu=8{F>{ld(QmIU6ut+WRrZc>5t& zHv#{WH2pI@%4FeAH8Hw?ytV89A;Yg<8+P=tyn2IGQ`4K8FIH%?4TPgXP&2pHFuA}* z5~yb}=g|E#p=(u>P;aQ`#GL+;zomvZrIX)b@>~NcmGbeW;o(Y>PuD8E|IN$&3ih9y zv-Lgya4deww5sU;yYyMf+{D`YKW%@->Kn0GY>5A{{ox;*kO(D21AHX1KuG>wuiMYR>OjhaY zMc3{3^WgsHt7QJ+F;n);hfK&2Do>$iL=-!E=~HT8 zic|HKQ=J@^vW{O>+}~*KP!``Ap3d!hIf9ECx^vH(fPdLs-4YyGvb|gQRVw@XeBc<` zy?kk!JIboRD^o-j+Q|y0g3~5p1y>y@pi>=ABj$Jv^x;+CSFBD2OR0+rwK;BA$Q*gS zF69FST?65hLpd~QM=iZecIwrrU1%^rY@FZS!1eG(?xf=JQs3aIwOHNV3TX3f?o{Eb z!M(h?lBK@%MEO-++nEOX<8seAS-c^Gt1vVqlcBE&chNVKh8{_dFRGfb>(^Hv#tu$% zC(zi_DkSodk7&4pGscDf<0QvB-Jh02%c9Zk1~|rBLzU0Plf|NTd%!_4E@nfeP{1blm6n zwQ~#$F9u7(#_H`UnQyaK!RRDxQnnutBH-0J;QBTkoLh}^sz+Aq>s1lAxQ&N8>qqr0 zsoF35h3;r5VVB(+792B!CH76*l&C}qC%3Pc8x8|Rk)V2<@$Ua^CHu)C=C47EpE+Kr zW5Hp_l2Tod@*iwk^aS2KIDZ|iX1^e>#!E<$ zFSp%(Kmwew6uU*B&X=yDs7~a)kBrKmAfjdsX%V&3UkK=rAX=3S7clmMrweh8=V0iC zaJW1Zp2z*lu8J3<@-4bj?X2x2)q1E|&(r71xFLEVOWi}#=+7NY9);qC%cWUnn}>%Y z&cfi!tBLjvTxRxiIOijOh|0WzZ;YW7w6O=T3s7uPH;4!S96k>GZcBP_PWK}Kmm*;R zey;3jt!W_N?lYwi$_ldHoW8*$w-BV5KaeC7@3RLT>)K; zh|YZk6=cW*w; zyclwg$dCpgCkSt5FsG7JR4em4!+eRfl!+R~K5#N@Hw8eIC{iE$Hb39OF$@)Jx;Yjm zdhMbrP60!1+DiB#xj*V35HEN(2L zmK*;Nip%$ds_|OuLUK?cVyt#zLILvd%7eZsJDz z-Xj`(Va$>jLrm>lSGzz~q!1Yx+iN0BRS3XL+M4@NCP)n&z=@4Zm-RAPD!RId)A9%1 zwWLAgZ!rWi2!7v@Gc(HE%9^k8j@$Us?8`mx;=pm72{XZGc{E2rrp453ALu`r4at=R z9H#heta;>Vp9-%Z!%FcJZfxRq=iTsZr`)nNQ8cll;ML#TRCbP)oaO!_EU);OlT7+&3l8zIS4_K^nqR>SgZd2hGta zeO9X`-5W70jgYGfIZiwBTWR^9Km zVkWS2u;c-0T2n$F%Pb78pI#aOMgsQ0_Sf9tz+>q~oluRNpW43{32sRzeDY=cHarA! z)I$$nH@wKlXizH+eNtPtE8*~09(uA$=CqA7T+hOca=gVYDX)-9(r$%$@Tzx5wQg?st ze>vY81ONb(|E-?vf21smF1EJ+YeaHM{laNo6#geC;}cG+1W!0Rx0D7?L{pPICmX=wRFsk|d|L}~>z1^MVyS;ywu4`;`l?Z`J#Onb(d{4RUZgLa z&}HzwXCuK5&OQx5h=mTg8F^!X8iIoXuUY$C7!(I-SrVx4H1MfXz|1Csj;s>K0X>V# zhxk1J7{mn3oJ6NFnD+A+Pogxy56x`84BkAUE!h(j)B2kivHI>1r2~Br+pTQayDdzo z(A#~rU40Lz^2Ts1b8-x7x_RZ&3{s`3!wAJ7Or{A8QiF>|Ovm{_`ML19fp|JfxCMIf zO5OT`A{u!KO2Ei8lDftM&H0fLaI8Vmj0wct&|cR35#M2_1i~r`v#+m zY6r^O>rQE+O8yJ|V@s&9OFPRph;l9R-dE}vY#i!~dne~8qm9~T*18tU=6eOx;rWvf zRh+hOv>WStvC_3n>da17$tzlSegs8$j7D7J#Zr)>=wi+y&O#m<>hKs4dPz6_;H|85 zA+i_!c3u9RWUu(>UO8DRBA@If(mKo8BDs*P-h!r^j(JDZwJSGg z0Yd_aBXa?tokW1XkETP4J=`0Q!}TM@z*^!an%3*(VYZoQc5-Dd6yAF z0q`>h>NbL-gEX;(%xZYnfc`^>B))O`ZAqhcC&X-al?_3~qRj#N>Ukw-Pv37A?+VYi z3(M-Y#Ov+3fsIw1(ylDo9S)z_a`Vf_d&!GeGA8jc$ymw3t;*q~XorPfvH04HKTnHn zAmI)&J5zWcmp2=RPOd|Zj?0cy?Q8GN!_L0uj{eT`ktAomdrjI6%y;gpr=4?ApKnL$ zU0iC0t+={#O;7cc(@=@JkJ=e}5bq|yUXOWUs|1%7SnTT*l=-nfmd^_mECl3SLV4WP z*(=^ll#1XC2#zIbTHuYOlyNVg5sAvAPO((1Oo&74Y#Gpv#!f(-LEN=`^w3VxZ850r zv7DjDB;!@WBZ1nS9HarElG)J`)(~$d|GC5?E3A$e6CnjcMTpS1m}*40=q=Y#UE@Qg zsjUsU&Z3dGFEhZ!!UZ#3mso3-_9Pty4s*)%sF~_b-YC7oRc--Zf2Bwh1|=Y#)<8#l z0YsMJk1L!R2hY`)P87IWOjUi8=O~IjOz3^ z7(+x%Z|0~5;-AVm2-GDERv)A6*D9~(2Xgt$ms-!HbmsOmgYv0fVuPh*UG||?^;T47 z&6q1*x)Vyq*!b(L@ThPl7!46uTQPDy1;W9C{4_2ZG(Bq8Y29tzP%)Gm1TuF$RISW94cK- zi*>5M3hGu1fBN0)tuBy@)>ka+E29y#GC{bdd*4+xuP|~QmF{n&3Jo4)&&@3{w0-TP z{c0MVLJ!`f{QI3tokpJ5Xj3*=a!a=yhT7+&)tfjR)sU9BgmDfwPfrz9 z{6yqVij)W^U3&2@eO#KA=V1q6Tvn+mE3ZTwNr`14g{+{WNkN{w8>FhGLC=iPS9olj zEh^JWEJz9)l$0%BSwu6+l zqB|&9-Gt%ht?;k&pHE{g>#+;F9}5yf+TUr#p`9X0G({0EgTnPCo^Vu(KeMzeQ+B5) zT({1pMF~KhK}t(m@S#*Je-Lf$bi20`0xu(XXm(a@7dNuDH~l|vPU4jx{7Ax#(-3oc z!qP8_{4xv+AEoNF`t&@1o;AuV>&{T0v2mCcOLuPQ%dY2zcM3ICq@B^~wN<2XQyL>t z->H*~zxRE9>Y9t$7Nk)>sto%5e*TLBeIgY)nei7ug8y6UW&Lk622~SBLpvvv|Ho>t zi;{xf-(M%5xa1%EaV1R?_$QkSsRibxRZ2#X_KG-ASi_~&NnXi9iyt4eJgLTNR7BS9 zn~s}quKtI!KhuEAB^>G+R}i$R6LIm^2&yroZz<`CoCXNCGL=vQ^X70E`fiM3S9Jj0 zf>6%EF>Fw;vC9mgw1Fg(KE2kRnb|t9#9#}8G_ZLv0vGWbML~*`f4s-)3F0vwmDnU9 zvx%G&pM6Ra$k5es#ZZ$H^!@e42TJd4$iX=+U##R7y&(r`E`a7PV56%AS%f=oX*KQk zjUNJ<@El$=^PTkX#HeV}a&Y*WscF$Lq*M!ljRcfY-(sWDb~Gdu)u8MP(|{ESa5OTS zocDJsm7jNQ0JzARCsiSY$DnJ}B$BB?GsDQgI=kfd44O8o_nFs;>$dtlv37(l{>8jG zLsh;abc^0i0mW|}NWadj>w!q6Y->=9Vj&G8VH9H+w}CoojAubDs!&k|k8>9;X`?Zl zTb+5Q;Y3k`5|UU+e6_avRbC{8EQ~q#*YJ6;KJ%2pVE}8(=ZjK}s@q0(J}Okrse6)% zTN)Awf;dzzvRP5;t!a{{Fu1|N&4g|1M5I1z&!SOFwc1MLU-iUUX0jfz3fBDL8gTlH z5$5+$?-bl_f7@exyI}SZ#A5tdX?DZ5SBKHqIl#yFKuk}&($MnoEw=Y`k@96Zv8<)B z3vtkx0K$%#s<@YP3^4=C7Uqr@g(>Hr6hu@7yr4L1k4(YygXAVXJY)BtOKnS%XnbqG ztI++oTTS)fuEPKDfBN53a3rEUeknMzE6?N;{|cvmDLA%2k%)7w=9zoTLwBkmHVpuA>g0j!_j*tf|3H%|y+$rm z6z&mn1R>$kW5kl)&=QH;aheOmt^Z*d$ z{EwAaO5Kw4g0D$RCNiCDRsTO%UUW2BPh(_qP06mb1eXB=5XyLhiieopBbU4hOf0av zK)wOv4E_|UJ=w`AO+z`hRdd zmdFh!UgP|n(ITgYiIzV*MhusdN@ltS5+PYM1%~g%k+qDu4MT_Ldx8@Cna8@zlZq2` zf--4;l89nxRZ^&lK5&Fior6tw6k`66SRFOO!_Q|*@&VxH^fx5IR%p}d**OG~;Lnh^%^ zcFDx<9t@QMVJ!goFnr;vgD;|UFX_QK@sSA>7smQ><)Qt&r)%#{+5WEx@pQfAheG&g z+wmJAJ-=Uf%>S}X)*{GXW*G0Jnc>-_NEamjw_cfy30VjdNl z%@sn4%Qk;hq%n`~tZS#5j;Fi0Mg&xTy1Z8ZTm~UR0X|<(PfxuAqDy z^nb;DV`63$e! zPZTv!gj2N47;J2!;klR@*JkHQNVyLnAdo$V9D}ua^AU@nB$c6Rt|+VsGg$dS^z0iW zqgYClvAwMJeeLDCTj74qwC7B~5n8ybN_s-1oK;IW|(Z z;HwUG$)gif`QF$Y!<_FT^KT@Nm-88@BGc7zGbM^f-LGSc>0dYDALRZHR&Ddvk57(G z)TW!*Yh(Z|NzGv@3?<|1Gi0+%K@)=%EmQS{wXJF~_()B~Dw^G&E}#!j$>A<{GhGhhF67&(6B}e(C7J$;r*><>-}Gt=@kd z?k$aqL#x}ypWL7_Z4G5ez!Jqm zw<$MI!3hOo^16CnLs#;F9VoE?T0Vm<8XxEvxwz%c+@e-x!xR7T-6mp=f0RLZu>vxFWz~e8#74`DO1Fg#zfXJY&PXHAG z46-5#Z9Jbd!7tF#L-Dh_dTq02=2x+m!>YTrqwkn5%)poDzBHrx@9T93+6FiT6?01w zCKZk{jm_@3A}7>n>x9kbbh4U#^zXFPKh-=eo4SG+Wd;3x$Bp>ckU(0~Ww;Io35W{$ z<`;ZCA*9fiR48T-M8A8cTDMdkcrugY1NWc>`IQ{(4)v;N6P|Y)X(l0zd=Q~pZ)t=& zFFX%!9|g4vW9g2Fnzoh8)~d#9jtM&VTuK^ea+ao=161*AZ7=gFl~`MqFe!BDKI_kb(qq?RhpZtb3HUpM5l~w9Dv-onTRipbQM$E16h4)JgRH~VrzrhU zq6(TZt`rn9L-`*q;|kQCewAne6#yb}MD}YiddS$lPQ2*Anh+1R%pb*d@@ zu>pV*CUj{sw8CGQP~RNYsoeHJZQ+;*8o4MO&755MY$d;1Ml5yAJw0gh@}|1uMXI#L zXe#v}2x(<>6?xSw4hlpKlp^J_^f|SZGh+ikgBFv?xX5+wH2MV&Pk;JPO+Eejw`T{x z!&$AlAc%tYD?uE2Y@Kv0Zho3Jc|0a#r&taNBoASIE(PjG?HCS6DRIJz=f8sUM9Qq5 zg7Z`{q=phRFaa3Y08IUyq?Ax&%L^tBG>mH64`9uvM5C$*rjZA>KqE}#!iI{IW*Nof zI7E_GSxVFu|B*FLjt|J{@LC@uC;zWe!=&wt;BwXWTJ)GgS4<6TJHH9>XcTdx?7%nH z;%fYV^ID{9{lTp%6;n1;DQv>}6#AiB7E>OaC2q{PgTmu<7NOi44JrvQSJ5@hTGlep zUSz42lQT2KLO&p#B@-lBW|Sp{Y~@az*)s6|Ztu4G z@%YH0_qrRnu56L*_yppQzs~-=JdmKsXrBezQJ%4a9MUR53r*NkpsunoR2`vGND`R5 zHt(!3Q$P${oZi>zzh#-lxV#YQ!fa~yn7HU@)P!8$SjHJXfn7woW*dyvt)m~0`E}A! zYVqf&b(~jVOlZNq3|c=n^WkweWo^~{tw!;!jAV;N1+lw@Rl4!0r+!eQQmbZHXMW8U zfg3IW5n!DGHpy-+*MF%vwHO&sh&4gW8rQ38*v%cNw1&vxovCX|Nf;2;>R%m5BC9cG zv;et+m#Eitd#|8x`c~ZK>s@ehP#a(caNr0F8MxI?7?68@-p@Pb9kz(+`vx-o+fqNn zZ^ZrhV@0&RYOh7tbM@V^%PmS6;ziksICAf;`}pts#bj>6HgNILX^05(=G{wQ)+d9W zjLg~vU&+nn&D;Mif)EGnn@YA{MP_#x|{dlot3t2+qP}nwr$(4v~AnAD&6b5XWZLopFX2+_wN3?ey;J3 zh&dx-#?xlK%Z+G}JuO(YIM|AqI)6Vf*6CYc6R@McI+3?Keh75U774_89zY|GdO(tt zmrb?!E_;OqUUq(3i?h;Wtyr|Tq|8G}7ewHQpm{u-q44hu>Ay}<)WCWq&p&{G0s${Dv;IGZd%yzzuW0YA zAZ@$A2j3++?u&k;RG=ryP0+SWLXJ)$8nKXqyK+(A*uSmqGQx(i-^2I?VIFzg_k23# z`EYy{0?>YrfhY}SWs-jeTpZowT>gTHM@ira|d2H2G(TJYTTGF5l^_06f)o)7!>S6=H+8Jya>3V6)xu z0)3;SddkiAF-JC1X-W#8G9?~geF?$%VZ5l~%0qdqx;t~iLs0>!v`k6KKTbO`3W7KWJ5#5-rc4NcXd@p_%a zojLh4Ut%fZ?PC9Xs|F8MhBWK-MJ7`5*SX^G6%UzwA(D|6zI2S%9do+OYO(!eu86*J zTqXzGvT_|uL%F=-4AjX${!?viK|VP? z71iA72R3ejY~5by`^cfc?$ypLV8rvU-xZzTJ*A2NWgu4!D_Rc%M5Ph|mj;~w+fT{d z;GaH123jM1TUsH0*?;|4l#Zg>vR4+3n@DtjQ>y@)u$}k}?^k za6$qM8WDQ@vk@LwzCB=k;h>NS2?9&^?hG+P2Ch9@w(V-bb~i&0rl(*6AgI;s+MCdi zZ%dWF1!vs+pAeq6J3&)JP>umLYKU)Ya;Opr)GpH8h{J=Tc9C|!8R{Qp(7f@vz%d@z zy@RpYcd5FZm)Tb&mZ|t9|A-JEk%dE=<tXMf|t)`l%jqYL~j zbxi{!hD{{nBTM#k#ndv02p z$Oo$oKJWu53?FVz-8Ud4kfb2jh+8MlL)n2+|dr{ zE5WiXt)^Og;2my$JPp`jm5%6p(KJ_@nh~_Sc_jb*q>s@j!yAmez#ZBYd$25ryKDe zv+#P`B0t^?`2~1Im>Fr_YMDrP2nl8IdKHcCaQVF);zwh1=uzQM&lGb9WU)>?xJJyM3-x5bF z27(RB=qB#(3O+f6JkrCyA+kdsNbNgqqrm=hVLRP{89=GV(YO8%!#tp=29$EFeTKU7MCy5pidY z@GM2r1fxm4no}fSbx%%CJ1pYN9#=y@i@D18sIWg=%q?vk`Gg`3Hb_8;Yyri%-NR&^ z%G9duF6^zO&<4*U-MESo(+PCok3yRDbf*63iI7Wp#GXoh5|brgddR*)iq-)$?H~U3 zOA0vJNh1<^5f-f0tcHo6eo zamM6W8+zNKCQvtFkOY(H!lw+MCy$1PaqPexjyt2_DR#{YXAAjz62TOe4Pe1QsVRIt z0{e(Ms^;3P$Yo$N!RP_zjESM8Hn^q|8MuW&=?WzxDq70kJDIQ-@)?QNLKxMAR7cbD z{q@V(7{H0=Wqh~y?^K2B<}2E4sfL`b`O*`5BarC+6z(h0bRM|c$n-3q2mY-3N&XGa z^e&4sO^{~3IJ>7Ps}#treGmT)Jny$77p|Ny25f0s+uFCl34_Y}UyeH?^nA(UvRvP6z?elJ9@6t!iroTSz6l8OGvpgyG8)U=$&pNHxkslIjY z+z2VEYHO7H$bL)c;NP!-kAmO#jCY9q4B24VTkEsN6j!!Lu!C!=lDPiuz;P;Nl{-p~ zGP%j~4C6$IiTdWrnd6_8NF^g`N1mV(O`j@ebv8RWUZ;_iy0OE3sA7>uO4b+Ibd<1_ zvnACW4eJM`PzsbnS8g%8W3E4^-hoL4uE3Y-SF2akzIq7$B4b7~q^PWUMMR4XxTr<` z$|VFTcZ62nSRmI827~cl)F04an$EPo+neE)uePf(!Xw$VkYBwMT3iq>F#x=%nf!-C zd)@RBvPBt|bC$GMtI%7s2Qc7aW#x||$!Yn)?f>O(2ny^m%Q zxJRwE<9?O?V_lltk&@M{ogy3XCGrd?>!|PGc`cElX|hilR;??JV<^8u#Qr&v4GRhu zP0M_7kp-Kt_4@;zJI5Y3>NfYCua9rGC&@k2i^toI%Yq`tt@syv?a%xGt>pLS#{ym) z868u^vli1dQ2r3uug_oqIw#+>otG>C>``byQJ3QXtKr7j%GeqpH#+_=JsvRa2>-`# z|2p(^smlMOnE3pP`?jNd!$%|Ede+B6MNTuItmGJ>F(6jYfzsfhyfl(0E@#^YgvASg zZzLEFnI{TESV-2&-=JQ}ws5q8txeqC+o;HohtCnhb2|unrsb zJbOeA1>6O&CQ@7zA6ac-y?NU*-EG6aNN);f}+XWdllh2C_`_YRRdwPw$Imi657Yi=xSA<&~9}aZQOb?*1S8IC@}caz^C7t)Zk@f!eWDodrbY7zNezDs+S*Q4(ahv$(E42 zYnb_%u$&0S9G{`ttOW1|vHjb;mky@#{R7qr~mXT0d1N0ka7R zX8taR)M`p$AANG$V=Iv_0;!G`0^8y+Khe1kW=gTEs$4%Z-_Pi+fR8{rrCq{qyCi0n z!e3+7mafcF#IR>VBprpuei;?ZJV##kmZBQtAo7-L=W|nA!oUuh0vM~S&e4N-W&R7= z=GL^?iqM=}7IVI>dQfXj%Sg^H#4|U%mQ@D2Lscd4UaKhc0tM1N=o>C_jKcIFrNWkf zZ-2~liDN!oDRa=K8Jo1v`>-yyFDF>DzdhzuLax(p;;RZvvTu>ho;TD}_Sm&V4`jTg zGRAKA1kw_{Ouo;%hJHroV@1uVCYO^gcx|zz7`^C#SB~LSX%!5d7WE-rjg%`D`ELse z)V^3S;dWublG<)}t!MKQ58=+}2ZOB|T{)U&ddutd4(3QwwU#mUpX5K+Rq}+WKgbI^ zh1Sf}?{-YAztt1(T?r;jU~y*HFKZU~b!h^w_FX%Y1vMEZK;B=f=DHc9`adZjaB>e1`k(|N7j0 zJJV6AcoXV0Lvg9pxO^Cb{5)wH>92TsjI`%?q221;kgVXS_=8<-zxxDYdrKJdZKeTo zv)F|WepTecwEoZ()}`^s@<5JP8LoLG9;!Rmo0U8I4fny4*INbQ@dfW+F_g4Ved-N> zq0_&BfRz6|3>CC>ws8`07k1OPwzD#pHg+ z*!Koz5Jx0MHH%KDq8C*hSgaWJH%;_Vk6~;TRG&~+j`$F*sLVub zgUk{bgHt$QrfqCN*w!-@%MuR{;e@w}#$YR#TEt2F9Z5=#o+ue_4Bh9+em<_+e9jE2i>=% zdXI1@QcwvroS)fbPG4bpk!Zzh5R5f4P^c#_ef%$eJZH%&4CD#Ff?)dgK6FHm-a1&J z_de9`@4tf#zy-UEF(b26QGCrDP4+V)N_6n*`sdv01|5+Xsv_xO(}6pwD&&f=B=sTF zVG;hq#}$liF6?sKuN&*FPgxXS{V@Gv68=iGU~Yfn#}nQjhRzE>>Q2zN`Igv?bEB^cZ=bIL>}}KHrbpoE6e3|Nnn@lR8>>Z zk$?JD%bxD^3gZ}d&Vw@bu_F^VN|x-`9l)AgPjFals;~(Y{E2uwrT~35Z&j^2yz*Dg zqGGCH=f9#$cVeWm;+-o5wlv)fR)w6G=;T zrTA)o9(2mAc`F09Gzc4Bo7IBf!hw0(f;F{e!*1a%QB@O#*2={n%f&ozf5u!%bx-f+ zS*aH~9wLxfJ}B=~A9}>f$G>pQ7tK@uG%6%Ad8OQaCh?p6zIGVVowNZ`wrS;&C?g3xQsJLHo6@ea4sS(im*>~|yo+Q|-U`F9rc#+d?%Yvu1}ZS%xHbqVY= z7R?6E1ruuL^9D0^6KEOMGB4NPl+#O+e)V`X`%kPEt6K$gw2Dk<<~8pc{zmF|RZ|vF zRwS{(igB$q6{o70QyQ?Bl(8Or?|+7l#4fz2MIoHug|OZe%~EkW)vDY*j2%j@L}J6q zkY3-VAGjNflQwZ}oL$0um#~UW-6>R4Rz4TX7fpO!FK=;&XJo;7`iHr$rRm@N@0`Cf z=e{m)TPjNj+d7WbtuxzuvXL@dDHx5b86OX;?rkKf0|vJg*k~dtJ444rtcpg&-T1`zZ3wrVSv+Zm46Rxg#e?glkxusZFg+<+2DO@7XfJdOrXT{ z_~x{(BMY6hZCnf86>@EXC(QtQ1I}s5S-e^P{T_Y52N6_})uaOU6pP{e@S0hFmXn>+ zi_yzxLOGP!?mrP3sjJT*dTLBnP%Ae*nLr+-nI4&jK@-euZ{o@&kWUYuAplmwKxxWx zi;+x%)%Hl++X$_3q*UpBlvQN}2i*cp0DFiz2E9UeKn~0!nuf6pOxQlEFf9~RcW9z> zsq}W2omyLr#?BlCgPv}*m}yN5W9c&?oa;O1M7PH`qee}8$E>1$FI-L2}vs8F3h8K z7Rx)hCtyzcXWVLG_AR?23sk^3bt8HzQ%D#yI^&t%84MB60Rk9VLKZPZxR(Gi8O^91 zbz4hm6{OK6cClBVGyz%{o_4+Z%VQARw~aT##g_qd@zJ`h+&{q*-UNDunUkTxVm!t( z!w6_(kwh06*?+*cyPov;B&5_Q?6^YTO(1lyge7r`vmxreUh8l0nRQM{WshTu!X~MeHm!H#Bsh>6`9C_)>0O4__ytlVHLYi0v9;y zh`+NXJu(#SomuTLl<~JpZ3}7mU8{-vC)_m*T?;qt3cej=vEQ#XtJ#g?fZ*Wwju6mj zEU1&T5}hgUcMBXF|A>lcu{U;E>yC5tc6aNxmgJlSG6oKu+M(bd#HpxsC@!ZiJJG|1 z4|CdXUlW}qAmc}nh~bm?;*)J4j%?ib#YNO?s3p}E$$`#|EdG?xd$Es56Cy?W(np|O zE6zE_5#=WU7o>(75Tw4g+$Y|@=R2*Wx$${u}%N{Jm9Lw;T+Bazfv={+>#M|qmYld z*!@SRnflje{+iCGgBDB8#3cy=D-p}@_Z?of$iaJYuI0ZK5;Q1b7nWtI`rlvmvN!(R zJU%8A8_(YhucoIanw(fBJ4KnmQ|tR;TbFCNi&H5s8AeIuUqbQK;#+(7Q=;n7HEY08 zpLU|#e+vA!xG_H^3WLR~^A_>dRk%7$wLv=1>+K}&F)b2B8k0e5k3<{q1m&lpil*q% zj5DFCW{10ve!bQYZQ97Hc5SS~!Kh&#m3Q{+D9unVd}1B(8E^jy=8{xeY8>qLAyV4D zjC|$$OZR>^)$6(1{sHb7)osW{<#Vi-)w$~l-@ z>pQqh8oU2@v*^XS@p>GJj#sa*X4<+CXW(WzRcx@nI{LYU*0feTR8&{R>pJeJO=5CN>9B0$1~ z3^fL&N_PMW>=R43(#seoltG$hjL@HO5xiC2fW$$WOG#-^fk95EFm`6sLJlRhvO3i~ z%i+6pMwL1dr@omV_aL)hqKAB7_FY1Uj`8H z17%4Sv(!Mpl^kQ9IkuKVNu8FPOiuCAFpKR$0YIdpAG#4nQ->jXl;-S3%+G@s#s_n{ zS8pdqf7z{zi)%ZEHuQm0%(ue5S3L%F*t2VDr_kKJPd&G7@ZZm7q#rqw2Vne1A?i_- zm?L4hQR#MdN-+qzcVXC*$6%R6lS9jORiWnW#P%rD^nznear(aviaO&qf>ZS;g~A|9(#(b1A08q3(G&t1-i17)Zl#c< zQi6hy#s9`^HQ+W#ZKZXxpVM1teEWG2>=Q`ZFI=M`x>)>nUcPk`;CGR{7&3vUI@!Zt zP(a5d&+?8(Hg|FHQ=yulwfWm3mT(^%K#U9)6^)n3Fj6Q51B1edic@Ob@-~W+dmnUh zPo^w-Ay1(yrGN}^BCmlIue(o8@)<;)ikW>iu-X%avwh~DK9Z8-{ zD?|@7u}Ttm@6?vN9Bt2c15o z1p5!9_t*ESsY;b6%K2Hu&^ z$RRQDX!>Rr5m-luM=i@ZiLQBs73aj%O> zg_^a-Jx!QKH<&LbL-q@kJbdR&Na0@O-qGJ7*%@4GG>NL8QJqmNL61UOI`=Rj^DF&F zrHt2>X^G6M+{l0Glwx(RhAY^Mh6|&$T*#N>rhbJQMFI^t`~?E*mKa#WyzE%M93DqW z>{V5egI*+dx91(k3&guYTixo?k9{|Hql2Av7Nf8l-&tyP%@l9o<--aaC66;O_qgMp zwE)Y=ClNaVVdg&Q;*8M>3jj%&JcZe0WBE$)(rXW|ETE4$FZC8nScsZRX-!WOg-w2~~KF)|6aj41OB5(+pjxmjOUQJ8EmFQY3+XSci^grOx!p(U(SD|+`V=2Cg$z)bxJo1=S?mcoHf&@6Vpq;x$LePvXg%Q>E0slfkvzj&(a95)T z@@W-rh;z@A7q_hUJNSqdoOfLWXI(ggR`4r+5Nm(>DfIncCu}ZR<#uF1_>>(L2uS+h zqY-f%M`H)4|DHNDV;9(veMI+pv#R67=HjOBn+iB7IgCwO^f(ne z!oIsl?B|!IH8h%NEu&3H?%I7$OiCXP_dwi$XH(ZS?q2(Q8z&}q^cwg8gLMgSd{#P& zB19{LERso^6m_H_);+pnG~_HQ1)XM#!wK+q;rt-TOur-q6@TTXMRTXjsK#-fk)>F% zzZQ}B9;S&F{_YAoBM4Wp8VzHgIwnz7n>uoa1bcqseSH#PX$S%cQA$*fNoP^-afuaXZDf>N<;s(T!p(Ro5dF3kyzHk(_`|r?jz4ss6|X7nqPEEsBTI&EW7)V?6>rStwT9Kh-xxO*MqNK6lm*?n!tL)Ihe=GWfLz~={K~)`Oc_5> zSNFt%X7K4c4f-Q`jM9Ty-PA1wq5)_rYUspXUHPW{SdpepJ$L9lk0bJkS}}-f%^f$j z0dnYO&fuP3ek_|@j}Rae7oI|wXumn-v?b8^bm_6X7wn<{u4c2b{4E;I8JTkx!Ue6; z_4&xFq8vYGB(Ro}`k3ZsGZoevR^xH_pEN>iT1sA_Nf;m!s#-fr5?S|XBQo3GQq{w8i9#T+$bx{l{z@>FgUG$zTMNszX5t6OV>De~nn?7zVonWC4f$a+&g)}0`9f(+s_d^rnZGgQ zyRKHXBcRmP`y_xH@EU11bKr0|%7ty_#iX;SgyJa5P@!AG!5Wk{(d6|_sf?WiA^?cb zgpYm!A(yQkW&x6g7zP}yk-PIFl^CsY7t*mX>&%Z8ON*iejFjVZ)m0|T7V2f0gKoy% zCsN92#9aKhAV%j^Mh8AozEw5a;QLnA)h>SmKc2?2+d7K-v8+)x&v^R26@hj-GHW@pDFfgVjv#crc4iwqrMo1xN@1FA(>%RA!~iYH+cAE!+Ez(E_xRrW(mj1|tlDt#lGk9J zGa8=XWn<4s-FY^216sce5(^L9>tj2kHJ6g7IklWW;}&Nd`_@4HGJvxUeo5cIagRZZ zyq=#YDMo0kG#;=IRp6X!_^!EDH5~fkxy%t5ocKtIhOgfJMs$8#ovrq>xqCjBwY_vC zgnn~3RxBKxX|wUt_2N^fcfHb~>#%_ircxh3rY}}&r!re{?_z9tGVZCz&0@qg#lea+ zaXe?r0skY^JXFu<8^ioA@({y*6dmd?X?CM9TjeI%(FOnW>yypv{n~@=^u___uZf(* zhNn7H4+u7YBlVDw4Wi5CYIm|OZRE4~P_8oTQ^>7t#RU!8A{>?jO_U^KJ?S8|X#AAixxDdO|d{CgW;b@b|1pl4#C6 z_S@@!s(JWF;CX3|$@vAKpF_YF^KS|~|3N>B0GY?o$=v0?mD88hbOAgB?<=~`IjJmG zR9584m3?{@ZnM@!nUu1D3?FO5U=3@7ZDlI?>u$>yo78%%NHWstmua;NYmDhJ>-WeR zkNaPs93U8@7J09FrrXQ?ebzJ@gg1=HGuhuKCR51$(US{77&MBK`=cUU!%Bw0k5DLS zIO?w@AUE>n1^%XcV4%-@m0n90FW8CEllns}|HG2p?`NI_2`*`yr)~aHsPrG4lNYMLh*;#s@{I zq3`QQ1HNSbQmh_&^KJzmY+;PygFf4*<-H9Q-Wwozb?4-U(|3ppo_II0=fsAwumJlw z0w5y0j|LF2Wg>9^5vf22j8_}elTV=&c+efs_swGrdrccE&}ko9`Pap{mMP3bGbmBk zRHrigO98SOs+-7r1sCfm{T;vX;-+{tb&Q_un$zd(acJm-0hbc`R7gdoacHzT!H|gr zP+IyHOheNHKS2S$WbP^swBvv2>cNzqU~q01zA$VXG@FeMCFdpHsPdh0`cFX0mt`zz2Xi6l@udtPv=?FeNpwAO7$ zjN^)7)budqaLM6hc?OZAYr8WNRK{Wd&`+*BV#Dg6OW7Lj%d2UxMj$I3a*UlB1~W}y zveaqum%K9nrf$_N9VxO(WZ79mFH(14D)Eq{O0W>ZdI>I$+bRKJ)0?qGarRqJN3X9R z(?8QzNnumt_A$r*u!}Sb+omd_s$9}9p*&nYM0Zb7=bYPIdoII*nLgVV7BY8T{?N7p($)F;Pm>^Mh zec-cf`Wh}J>?TxsD?|RvDAjcs!-iV0IB-0kplY>EDhbqmvgH8%!ti*V^k_Yp;htQk zv%m!m=Au<{5e=}%%io@`AAJ1OkDA%c=>Q7S@1UF5?Qd0W+!Cm19bzocm(D@1&-Hj0JJc*Gnnhi`1m}yor(^@@pS*$; z!+XJH#o@rk7rpdgIX%E|>Tvc&J`N_4M(~ozX49J=oiP!hGADbph}cDb4JhR>3#Esx zIn(EU=%69#qu0Xek!MMo@yKvT&bJ)xY*Ddwc$rVxJD9!9{qotCl9P_yu-EG}R0c@? zf!~4jyFK^!%iyH$Zk}&aHy%!;o-B$VF@T~?PP*kWpZg}ZN53aM2(L}Mu zGebevpB=3m6FgU|Cqk$vXecEjF}d~&ZMt3z>Wr>)It(3p018^`g`p?bZ6`BZG4Hxt zJ9kjCihah7ZLqe~~ZA&`GaHI33*ikj)f$BX)7O$wO}0c+RuE+iI<`c^q)AhE&uh z6y;4|!xkZgW_^A;tn^S!+R`WBWb$5&Uzcq5au~nud9!NYtXmjBgqr62YP8Fay;%n? z8O3YppzS5zgja|ea)PsbRp0ASxfGG{7FznJ-ncd$_Hg{&fsZ+S6u>{zw6RIjg$r?F z&Aqo?iZNl8=ZZ3rp*~+=|7z%lqNL;G0faPIBp@K&e{Tc&5Ayk69)qg6lbL{&tbpTx zw-a^!Cpk^;F;J_>K{c;;wo34dX>GIE1*;wQE&d-lO#>jO#jpb8G?^soiG(d9K2gvX z;_V5?UpFyE9NDAFs7^>iCb02n(u3rZ&Vd{lU`f3bm4Pm>h0ugh5*mf5L>Fcq%wTg6n0g42~C+^`If z`AXm~j7y5d41mJnDQoGKdR4SFppf>Ya z9&+yITU^<>IPru}W*`7vpybMC)aU?tOE6z{1)l*JEs~sH#Q<#GFAb}Ry%ghPT#R(# z6>>E}(v~cK8H0UFJGuuJpr)z%p(B$!y&=F9!oj@F(Q(|F)PyGTj^vWqZS{1V$C3;@ zKn$zevEX*$$b=jqaBK7VK7xH=#%$*RA$lG{+A zWq2_P5HLVRWtv!3Z4-DJw`CFucv#Rxe}> z7$hDTs1<1K3Ky~Ma>%SCH>XQR*?VV#QZS04CM5fz=Jk~`^W)`8^VN7oZ@60mq`wqi z@uSoT_q^hk0nenl1)fVmUZ54eETW0s-H9B64)$_pP3gsP2Agn>UF67?>*1RiORxvm zV^z)Af)x|$D2Bk%jDTDiz8W6nIxOpFs4>XLd?lR=4qgMYz1Ir`h+m-u^>QYM(RL7u z)hG&($#=WKERzot3)OiePO?mW1fJS1UHoQ_714QSPDi`PsMi<07c6R2KCS#OCQ?f# zMgh!qtQsWv2}YxG>3#*f5)4*yn!hbXIAxjBl(2f5P2X>J6@ig_8bFzbP?DaU#7a@? zPGD2MB0-$Ll$-d912SH(UFh9LF+fGvj`prX2Kkdrg=GyTR|-z0T5{)06zmiRoLVnP z3UD*0f3_=a7F{+))jxNXSeGh6VH6w4ag@f@%pQ>#ukfel5=r>57IZ*$Tvgy$#4X3u zu7l^Vcrswd=0wvJn)Yy+CzedJ@@p6x1XTM@&Q*mcNHXk=!5E!K9g|FH-ODJIhX1sL z^QMgMu6!Xh^h(j7^XKyS#AH*#MVQkv+M?69#Cd$kzTUg7D8@Q9@+Mb=Au}lDesJE` zFybuP{j+=56g=cXIFzArSA77_Q|3jZh~=b77-dc=^$T46;zyhMcVbEQR9UhX^vIS7 z&kB=(?z*x+)5KAkO*$6tvCfYq-IsHkOl_+TwH8~p-(OFx%Y=8u7ZP7wQ5K@m9k*}H zi>~dr1EoK3S~0yoCYJ{fdRj|EjhAOeYk>PgzCDdqr4RhqmS(xrv^g+?x17GvyLVG;_spr71#Gw(u!(7s&kul(+U$d)=fSTYcf0 zyii=dn$cBD8PzP_QmpDUnb)PWI(3KLF|yn~F_Lp*B6HUUqU7{x(YJ7c!dhNFuh>Cc zC_zQ#$RQzR9^Rzjl|IQ9-i(H1RLo}j{VN`JG(Gm3PcHgvtqgX!saC}pH}ckXXVP&y z9CP2*TDi`Vtx{^qu^W*F&Ken7o5CyqHj*)aUkl~rt3`1j-cjDTQ2f{*Y5G|J^>$oI zc2g}Tw~E5j%bIuA^rN9Cpo{Tn4fwz|Eeq}2VNcUjl3fYC)u0;s`M|i^xPKbXqa?N2 z6FZrz{9W{@ok|$aHdZ>vQc@ciD>XCI0W$RKzmkIlrG(2cfE>mEY-xwum43Wr-eE@7=kFD5 zQ$VeD0t1B4VjGOlRA^d&F3P?t+;IRL8JQ6zS2 z?c*P$&ZQDZ?zT2;@Kjm|Px2S?@HzC^zubu#TDdj+MW8guiUHV>C}gk(HSxz)2Dg;d z)l$c%dQddk1!9<$M@)?jMd184>(0cGqc{|YHed&shoM|7-Z%qCh+isg! zGT^B{qK570F}rc3zzYeuwfSxTf^Gi_v7G@5=WYmkDL0{os4z02r!a$or=&9(?_(ej zaUcwfv5Aw(`N>ZvSf7SghD38**uP*!64>4UWfZTw$k>NS@kO_n7 zD|9NAecew@=C~8HCxUYi6u4)I00l0%p+@fIK^3T9uLeybv+mm+5 z_KzK`cm#OZ8#|Uj9}~mH4e^*FD+zK40%%3}5%l%1w|gBqy94T>KjT*49*eBg*}Saq zWC&Cw@dVUEr_$tSLS{S9BB?aX<3rzc6go*3?xa-xO6BO}w9u)y66PguE7vahflqFH z+XTthE!{uN8OGUZY4e753(jsPdM`+f{(R_z+)jlxs7*jny4@s2@d?fO%`yCRCq(l? zuWe9PI&{eaB!vWhY-3(|d%?g(K8zsD0w~EE&f}zp^hdC$wtjM2Y*p&{+g~a#wzj_a z2~PKNj??@qT_J@FpqjEIw(LN0A7bnZ%21vb2U{4Z!BACxOOI;*n{K{mc;qa+E=5kD z5Ft`aCqolGXTqVspum#;Fd#6YrvMt*R|}YL=QM60LR!Qhl{h+n8rxV)xzxzpuDMqNo^nNr~SX zT+<>Mwq#{PRWOx)_U26cY+HM6?5LP3`>hGmd8P4N^|x2*qOrvy(ovZe0t(!*&M6vR zYz1W|O$#;o1}pwnYft@txTJ=r+^Jp?&XncA#fsdO!`D5)chY0QRCjRS`yOwQ*>PO0V`>L7F9`l=8@f>a7 zn(~XbE@fOAN~|@m?i@_;6pZ~4n0MSPJ3Az_Vkj2*yYi)g;24vc>-@Evh)Ol~u7d45 zmb#73!X~YS%oX3&b!s%;;~U7T$xhF@4L2uNt3%dYF`ez)w2Ce|wqco5QmRZXyX9*C zotTHv%cgNLljbi9++Tk5JJfg=!_g^{`71Z}pFJJ&8QkY0AjqAw7Rf{yrs2tweN0sV#!xU)rVPV_hxc(OgFDBCMZ$Ir8d|9U`MNmY|pAAhJdspiC=D_o2DgR;mU62W2dUlPot!M z{k?+gL#YZG*a1W^s=#&@mB-8BZ)3WM*Ibn@`+0XWkV)@#uBGb=e(?1Q5wbFi1-Jb; z^10`CO_Rs?7v|NGAl9Y-CY?z>u5uGUvOds0=(L?4Wtlozf3TFR0BAvd+602p zK9Zrh4PUT*cf77@bZiw<;%~qOgZ83}(~-&5NG!xd?J#OSE=>evc%@wkxkO1Y3=sm+ zR`4G!H-urSptN0J#cDEFz#_5|yqGu1GY3b+wRA`#*{}8R+iSu`9ZkK$W^xPW34*!0 zN0b}w&X2mz<^>v3lR1II(v6EG;cDKaeho6^t}fSt941Q0RQC5PAvY%;AKTQVeXkf9{u5%ctF9)}@PuDuR6iKTvzB!I^|2>j}vw5(>7>J}+Z zt3O^M@?K88a^JH;MJoFH&(IliN4tz%4VpCSF%pGtSQG;ap8&FRB;^>I6zWY~o%~13 zdb)+EAtt4Qi>j#rz^?x+VdQE(Q-}OE&Y~BvN%WlhSt?>`3`o0a@vo7eb!cLEau=;9 za*515SMSo-v0W<)r`jYPooFfe|3qvqST6?Bclb~a9h0@`VkhD{-lQg~R zYPYJZtK+TpqnPEvoT3*8p7}UiqtJ3}-q;;&g^lp!=ZI{^FLNwuw3$X)@K_vtJ?Dn| z!1;?Dfag{%F;Y^PNn)R^IPptHbuARdo!FzVJT&)#1tm@$;M@mK)u76;zThfmjw}M4 z``t+!b&92ln0&o>N?0VOkqCbM{xZ?j|KZ%j7*>2Vn=wIybr&;pNsl_2e_KWcQIQkj zPkR~DP6%XXT84m}M9T`MKPUd<+&h(=^gT!yHc61uEbWf-t&NuVHlOWo$SB>D-iH2I z5RnCe$bUDY!{)-$iplwWJnVDHAM6-ulU4;0Qym;4mZit{rnd6YIOq;x4-33v94s8- z_Gq6{W-KNt(4g5swj4cvCtm~V&BNXX@voh?L;ksu&m3A0HT3&78F`W3nP2|$MqvqpOm1EG8ng%rU*Az|}K7rN!sZ9GL5a7MRM~rXtc) zMWS&e{?7nzzYoXv(szsYgu++*C?_kqpR6vthh&k^1fhwvLJd=$yME*J9p0P?G2O&B z>Ly-_OydcG)q)Z;)7hDhyevyXqZ zQ>lr@OgEV#=n7avn+Q;COZwXOgz9mdKR^n8bX}P=y@<(g5Dn^Rk90hh(0IFU4mM|0 ztqd%`LE62qQ= zP=2IxqvroTj-s>WMElO2TQ1n~*{$A^Pbo|l?y!K(DellmAD*0PgSAzSgTDj-rC*qW zBOzLea}5)TiH{`8Q$M&*Qr%fOn$oY+2(?M+S}Zq!}C8d$_F z+`k2L(tRnrid^_9o&wt2RO4Xrzb^Ehc@ajYlR3pKF~8shztO>Q-5|D^xl^L9{H))u zB1v*shD*1x3v1DHQ+Ld!OuNBpD)3hf{OetO=WQh1ry z;hHeTHqPO70__6l4W8&H+6BMA!2gwnsDl~qDF9(w1=xRE=u);b(*I9kS~-0OYe(^a znzs$D^c@}l^@gEZRU2@_fb9KGlV^HcdwOoEGHve zzVf%{%@cYQE0e!VHH7bEmgCH4Mmi|kiK*QWI;A0ziKFrUr=_JAI!%H{XoLl71?Wyx z%srW8cfu+qc0p__D#J-w5fdu*>i*SoRkY{~z zd8hT2etmlTGC+$WNZshOWp9Qw+HvH!a-Pca4AAZ!w)_;EBa-~9W%e9UBoRYJ;*3r- zm=YE2&>-bsuQi&6J(*gpMo6`Ube{DQ0PIWxYq}OUI*3rrkk~?j_AuW$u4d;WLjRrJ zPIm6olD^<{Kua%5T{Z7hg;>O@s{*p(LzomxZjz=c*zD*dGN0V?9e^7Ah?M-QJD7NT z^SfkhN<54~nzbjHkhqrql`q#M6IiwY!tsquDwv+MpXxj~OqOvN3a>ccF9ecYi?`Tij-f9ln3Na^UL28uH?o|g1l8n^O0OC7ny2NORrKGO zScd?}m8#SOOt{p>6*()~bj|9v4U8#COyY&*A7%JkHZLX@$hy+WNG>mbiRzY2E}0Or z1>R1+F%B462gY zCuAFnf?CCrs4Q;Hq@2JgFH`W=PNY|gT@cjLuX7SAUj1pS37Oo|;@M=i)s4e4%?)W% zO8h@qd#Cuk`)=F2Y3#;EW81cE+qTh|jcprE(%80b+itwC_I}oSu=e}Bd#$}cJ=G=LMNi3Jm{@`o^3lG+O&rj0y%att3D9pAY zr^m(xOG8fYK?Epq5nka}E!;PI}-#g;j7<7x*-&TB1-0j;c= zvr}G2H`;t9Dr>!#*q+TqSuIuA_N_4GnaNR(uczTZo@dIsE$%7@VDVn+rumgnT6)FV z5}pFEm7mTjcElPpNl`>sk9X5AI_qb-R}>CEdM~Rv>gtRpSiN|aSXvNos89FzRTj>^ z!VZ_No<4}xud2K1HjzIa%UYe6@OOPgSNw953~|fb!phd$M_n4T{yDYzuL&Fu-bri# z%cU9N{}rbG?QFPR4Ir7>V0`d?eDHyI+J#RnpPQ>yhY*{)CRa*&IJX!?hmRAjSdGT- z6*c$1zsM&ciq}ir%AqX+hXq{pj4Q+LD%oUujLp%hOA7Ym5E3(7x^411eG@K+W2{v z*@ZDl1I^a6{r8d*6hJTMC9kZP0Y)-9QTe0Ef$d4H4eCGJfp@h*L+Py zGVvWD58RN3ib`2;?2wBD_*Qrr6$08mnt`-6hcDIMIIjZ2$N;5~YqupY!a_q8XTkG5 z((8Tvh@d)T*+XPixv2}Acvc{|Ml8nUYc;A)2qeD3Y=n*6`cnu3x8R(YXuQLBF~l=T!2C` zSz`pr#eO6rm;oV7BWNNDb_FdSx_s>CM1zVaZVk=%wG7#e`4rM{rKag@d7mF@x_6|> zNvQV+zOY1f$LoP+6z={mCo&yqTtG=ggpPT!6)7h_OS%B%({82<%w?<)p-P>NvwQGA zI{Ny?kTV3MDD8ySNRgC?r(rF5j2=$0QA^JA&BDwv-A-Cfu^h*L5Zrq)3NX0g$K9h$ z(jRd-a8BbZ$|+@|TCE228BiGsIQQ|KWyxcN=v?-@G5D}|gzLON7@&y@-BaqqNMxmb z&M}dxdt|%nF2_Kq%;5va$+CkFqh4$dP8;(tVjQ~D7-fnZ;ew@606!jV|cxn892gWjGKTd1LS3A)~p z^YS&RL^4&C$BRS83yzVD9H1Oz9(S$AK&_fvg@ar=;w`Ant@a%*ys)+V& z08K`AfG>RDVk5AH80P!0ROX?`58aR`!-Yvb)gZmykAS6paqQu$;4>YUb2_WT!z8Pq zy+@<1f%|AKAGQ){na7Hks(H$??tY$w)CpbaI}9vtSRfbwBJ>PK1I(jY;Df2YkIpfrRzB_`;qX=FW5lq4?9Ey`;-W{-GfvLWNi8*;{jf2}o*?}- zt8tjtya(gb_f@S*(yCXvoT)m+a|h)1QkS_cNYs1XF6^3Bil*EbK81BGiK_B^-3B_c zVbHiqe0Q*wYvFRuSTNT85?e_~Y)wWH%d*k84m94?Oy^HiHHbb zDFDzG_hU(k-i;pF5Vd zXp(tG?Oy~Y(rUCT)82H7IU!n-1HCODQ~CfVhu1_?!5k^29=RX%av=Vo6{NuDbnyb$ zzb+DFO8^I%c3Wg^tfbSJcy^KpyNh zA}B$ZYHSruheS(;Gy<)V09_@Oh~gJnk)J}_G_jvIvb^7&c4*r7_#GBF9!5`)=MgLYt=Ht6&1xoGD)C0t+ET1Q3H zi2RYT=E`yQg(^zb7qI5rM*l1pJy4EpD`P(`$uvR^EnCNs+hGTAEDk)J%}=tVOZ4%X2Chie+fZZKZaNvJ3blWWHXi1haoqURV@TQ2LwG=F`sFuTcLdz;-?A=mk^wvkek$S$p~HmXbd`~sIkuf2 zdBL%Ar(0x=D6z75j`CHe8W; zy)=f*OwPp_omns+n2;Xl(1t0?Bv!*@Mq!WuYqk{`ONU@`0&G34Ily&89F!U!Ovm_4 zIrKF>D^t7M@iny&*n&xz5gs61qMYo+nt+ZelT~OLHZ0i3>z}uOT0v&|%NJ>=9kh8U zcdy?_%%w^>fNfSGWc#B*rFmDc6kL5VWy~V0)``^@^OSX<6EEhZzo9Ay^o$18S+?Nl8PQjijRA`v~^;jk3^aU^+g?UfzB;; z@r1r;*x}`BIQCN9*)^TOb9{Tma7wH732t!!v3!qKNH(<3YmsOGpRdpVk?G57AW7_- z3$i$ON$=y-ow-*=J@%t9By6YTr)DFfc9DO6q|B_2xA$0=dcM=NB3TXQ z41EB{VmQz)*yQ-B3>NT!6WP0N*UwanrIM~~snvA?j7&E;{Kl|{)k!^SK(}!Y`Ulkg z1hTtjml9U=4G!U;uC!Q(@C&vxgGPD9H zAo~_}V$a~3^Grcz>)r=C$2A_Wp+l_a(u^y%NdDkX0#U2|mUyx)tq zxz92~IUHd+4d=!?0onID!sRx%>r}Uqjc-6IN!RZbqW7Gwe4TD2Y~7S;W+bOEP&sb{3Gi09cc!mh}w)sDGr>FLHQpT2P}xXQMQEe>JUKx=^Wn@o8j*@IVXn zCVWg8_yg)@qD4|kz~<#&pa%K_>fh=*XfLg}&QZ>osxmM1j~gxXsv<`Ywu(jOPZcD> z`ORnQn+)d>_@TYjq#h*4s@COf00`82AUxOQk7&hoKHkWehjG!x}~JdHK=Cc z7_$Ghby`^dF@8U=fztPn7kwv)@O9ivhf3=S0f}cIMXwAXuI~bKpi8&0JoSC5+|R&E zsx5J&$uV5a+tqAijn|@ucF^)%-LYvuM%1Nz4DVubzb9kp;N|CKTO=r=;*uImd2ffy zx{cl6kWEjP91?Iy?D>f&0YEKbK~?MN)!l@}XdFMyQ3tBv<*mp57pRZ+0HD@ka-Spx zq#0o9yN#7p>X|Nk8Vd<~5d?>8xn6|e7_UDWg8G@2(|<=cCl~b;Anp)=9tPt!NLWXQ>Gm9nw9Xz4K~Xn#z22+Zm9%HZWV)2pI}T0b|tS7;Z`gexrjCG zTPko42^-ODBMy~Y6mOjs-+ocaZSEph2r$Z7AQip_O5};Ch|PEk zi=Iv$&7_SA@rhQE@YaS5>~Bq}%Ooljd1*Fdy{ndQOE1TvpdLJ2;0-cI&)3vkV4ac<5Z?k&%|*{&te5=tCmo9@ z#C=^lmR&T;$99e2W4Z*FkI5nZZl`PZ?$CWagvvLy!YzD%c0^Ic3WC;TJx!w3=hg#F zk|${Prto)}Dfo%zU9I-O!#GZm@;3ST?UfRy zOTbMb=Q6880Rmp_JxBlXXTP3KlXP^l@gjqZ>;YfY=ND>{sg$Tr~i zvicmi79{a=7%vnJ`Ta4bn#>jf3-J)7re93g0iwAyG_VhG^TBc(aM{ibM|ks0oGkSD zRimE-_L&Vnm^xUc4g~*_zYi@;Pn7d5y3{*5uhdqJtM4Y3w14`Sfk!&@=&As5z|Gb= z;ATsATam8i0!MZxsQI05lz-@rSpTmM~h0{Bmr%Y zOz|&iU6~(Ptd;B_|FWFe-BL{YH)%b4p8x=M6b4{;c=vmF_|&G=bZ1E7B}LaSML9EZ z{QK0mm$kvjC)a%^q@)@XSGEM*#k_S1J9d99TKFWns8Kks;)6;}z}@gQ7FT+KT?c2E zV2Ei1BO>ZAWnIj*?ctpOP}a~0c*YKcM3S*~xW>!~PhXN#U=WL}=vz!1_(yc{)cE;` z{^TJ9$;jEDNv}tcGs6fCpyN7VQZDIkif1u2zXzVilwq592&GS4VnGmTepjy;l61Z= znj@f^S!}=lt}N32WE(JIRhEZ?J7|fuD-EL@)79>vF@5j2d*7RKN9!Ib6I1wmCJ0wj zF2Q9Ct+bSII3=>He>f2)Zt+&H?%U}{jrjY7*K^1YG_gmwb~%qVSsGR0<&b+!epPh) zb9|rUT4OcKaZ-sHw(+eG;DmS5LIczlmos-RK`CBwxD9m@pphBAncoODzL+rKW=02Z zKhfHz!IUhMiV-Ociv_HpPVU?dB_o>-;fz{YA#i2uDG_KGVn>;;;V|gP~hj0l-*UtCU9@cA@VYw*6Xb)8wU6=Xw zuB1$MMSzTFky_6*NrtmeCM?QpPR}vZMUtGMqYkk;|JT^Et%1TKbbar0(PSt*tA~y)(5CxoH5E5@K;b^^U-4Gks zfAe4x;I7g4Za+Oe%&Bn^x8I(}-lzG>@*S&)!u1u848 zkXt-toaC;0a)tMPwlQmHp(S;LY)cKhsTZbAlrq1q*)39ip{HexZkVYV%wvKFqY4Y} z%hHYV$)2})h?oZP|FwpT&E2cweK_@cQeN|5!NaJN17gD4VeSS#2?r7Y3J6c_Am>FG zR}~TDoKtID<=VBj^*TKcTw(7gP!Vf-36Yp_=!fP@RPO|AgunsSor`+3j4` z)H{*cEt0@%5U|~8XFAvc!j{&cjU!4gD3L`RK7(k2ZABVsRFFh06Z$GM7z7-2M}7TL zY(kzx1mYBGs0Kc@P|*a8eNgt11WH9?VSK|=vTgFkLajL;7vmon$B=-m;a>y`Z%*9# z=Oem$!Exqa-^BXFTzP2GXx>sF@sOnGXTyIwdI(Gf&0T%xX6T&ax)z*Mg^ey&f@%G! zZ51`-a4|@5FFCtPAim&>N|oD2|1K6?bc$UaWshKlxt}3CsGcgP+qA=&W!KI#a>sa5 z7#hvcY#3K4#uibaslm8Y~MY|34 z?6Kuk6WvBoOMZ|~=6)aOoybIrpL@2fd-nm>B#Io*^nZ-mhN1}SGy>ck0UV2hhe=Ph zoQCKgVv?}KCR<(W8EW}ywh`1ff6}7t`3k5DE*F7Pj8c-~ICttSbAWsNX?8Ef=5gGN zivtg~_f~g<2}7<@>h=Fc=sS?ME#t><#8R1=wr_M`=K$XdM z%F=a<54@U;q@X8>8P;I;2QfV&gH64z%=pcDJj*kI4!nCXu5o#g@uX#|66;wJdP|J@ z@QyNYNIiXa02*W(x9m!ReKIn17J2o0jImH1uP3#9F*Dr*)sKme^6~x97Qd4Q!aHv0 zO%_?|Zg2h$3r+F9p0)M2+otz*sSE2-l#tbu8*nBqWT()!p^>H&c-z+F7 z=kA}z9HTAY*S)hlu+l0?_CaXisx=)(- zG-75Jf_dtaZrXM(9m8G9wYg7bX_^Hmbb`%MYCOEQL6S6UF*-WykZmiPHm}LMo^eJA z=pFf&ESkZ)z^9)8o<0I%x{Uv4ThjkwEBsxg{{J}(^8jbzZ%MP;dUyPAi0q?(cHKyq z=UQA)*~Oi~bW3VZ9`kL#|a4X%Gu5(QIH!fBJh zXeK6ogN_k%vui@%108Hsey1dA^^Mt)14>}9t|5X3(9NJxQYzK!9iepP&1?OjKd`wx za}=$eTL3qGUmeBNfdnvznB&l@^e2!&yrSqByFi5)#u0zVcI}v`iyiO9eZ z0gIGk&=_|G+;nQ5J*Z>Gw_gIzXc8wS);g3TbarG;H^|U+qI*vndphb{(I72gq3|55 z$nMpFs0i&4(h>FoEBPn@M_WHl3qU&+*6eE7K(+0UvHP{K`c0cluN#8_G8GpeEcKfV zZy^2|U~C7rUFvuXAZo@MfT+H%i+HjDr(Z~1=`td#{mtnxW>3JLcWtlO(RDLF|BN7WCdvn{?}u zwvRbRW0J(cGjbS3{;g7tm=l*Fvgt5Lq*@K`WV8YjI(cd{zLEV3yk&=Rh|gKET4_0C zwD^dcG+3N zeINW>7gF{OJm{un!3Rg=kjSw*L;bF;0>?K)4vh@gka{A1?~hPzln^r}RJ!`9N*Ep7 zH&KQf&-9|%3gru~N)dT3(F^{i$zS5|#fs(Vd^av=?(OLlG}DE0QybfD5?Z34g5 zn-j8#LVxDPdnEQakGKK;u0bEDM?yht6jQaPY12MaKV35-v3oN0ob~r7>^8BPEq4~w zH|sdsrYW69;^t7WPP1WKTSdJycB^7(+tXr_L)5rd<}g+&uSFKkYv#gVimMXXa0eI1 z$-Nw|+|8`gt?q`3wI9z|AK>H9y5;)4^XUmc*u8V0EL?0=_=@NIxOQ)s5o>nZ6rDt|2(-M(FialzqYtOg>tW?hOW%BTQp^kXG%Mt z?*pWazplOjX{WAMUW_~`8(7P>Wy~`v1hG71=}rzknIllUH!!Xf8n%35TYKn_A(qc- zn*8PC+z|a(v^DzWW&Mm=NfNFBJDoDwbaUQuFY@@e4`p7P9 z8a}dm^h0a;rFqe+k9uL8e$vB|Nk`DUTDJYne?3)5Fm>U=LT53p)p$p(I_eCMLAt|o zq>3l?_*q8lw+sdP`$Co{;Q0M0hYMr_>eHvMe4jo^{kO2`WDH1-1#DvdQy#a{-~LEr z0jLK&$C7qjZMx4&eFdK*CCM+G!S=Azl11UPsZU>8A6hmlUIiu+U_cC45}OK78}_~I zB?UsnCnw(UXxQ$K3w;a%{QKng`fD5b4n4QdtB&&MBsjNNHtQ8sd-Ds^@)oGq*bVXO zj(<)>+X&*AS(ZI=*h3tRm`WT-_ZRXn<m0!CQVZEQC7NP@BQ`-$QZaY ziG{4EA_;J&5NRDXxO?t`W%$)K1FhViB6sw9^msX9bU6Z#?*a2tIw`JJ2=qy9`g0M_ z=GQi$ZB#cnf?~Ibo6pesP+t~6rHBBoA4AxC$TWttpJun zh52x$mVZnbQNj$fagX-M!x>23buW0%Eqn&58Mn^m!6%&o%DC9ib#0+&?gCq?QvF@C zY~Ai-5TOwmW~_PNSy`EfLPc_ zdYeS|dUqpK8eg9YM<{5fa2EA(8O2bm>*bV&nCcB#{6#YokBae~q3~4EP&YjWXdVSL zQ2{an^crZ5*E?>cyu>7$?|U#MzIqPcutQjuDiv|i!<+@&*QhIO0YuuAv{9iqknlwd zjw43Bt~&A~>W^XXlRn#UMKQRX5@Ma0(y3~vlkKIhSUXl^eN=+&K@nrn753e_rD$@Z z;ePPAwlAfrqOPAZTTjUg?0-Rg6FcOXH?aa5wzqMRbEy9$JIi6?H-RrJKp-Iol|_2} ztVdpu>kk`H$@1e0wg9?H^$h<*3-WLUKBT-5+%W5qyjvXyA`B?DW&lsD^LbS*SMu@x zm*t(9CzWrYs*r)PitMcLw645J!_eMzOn#G)SC+>Y;$t~$rEMFyf(bZjxqTNntI<;U zxXK2|99nw~MCM=pYVv9N;*1#l4`AWrof9QE03YDCM%)gKLW|0Zw*cHqA4X8U` zPU?!y*rE*?FV^`2i5F@ab2 zYl!XlWziHqX6C+{A{Bc35A0FZlQrPMviV2H^7m$637AE*M}T57!P|^_upHdOw1$CzAFa8cVPpGC%a7FR5m|lI?2k1>5bK0LHeSmIcs` z5ldo=wlK4=#7`Xxeqx?3r#&N?phwbT`s&yc>4}j2z9F1?74v5IpP|)F>T=q5G<$kS&-%=R;;3JZ}Y*A zU-TwtK>kOMw&sta4j0R~Q|dj9&QquZ;Gi=gF5|6z(~?p~)Gu(n>cl@6-*jO-b!Jsg%ne*|Z0VRx_(o%NldwT{F**L-hF}Geu#5gC3kM z*9~6idi-Bw;yLqt81v5UJ51jY5FJHhOtexEVXq_W9TKZTD&%0h(`^_R3 z_+gebrJ2^{)f2MwW5F7RKT3(Oth1jF2nye1 zqTd=wj;Kv5%QpJUQy)}?d5>&ED4sepz2K`w%vVa=h_1VFXM`%&32?WR=3_>2=K^vn zlf=U)EGqfC;%BW&<*n4OvaXva@k}MA((s=>RoC%k$8Osa^Gsh&MBIWsew1|CPKE0Fq?dav;z1f)>uTG;B*A?A2J39q_za(r&;{aOJGF+)>q;=Wt_6S4@EouK7aI>=3wPKt`BH zArnaR&rOCcZ&N2v^Pe=6HHyuRAm>Wtt`oNsOkP^hm`DSnW~0?L0hSY#P(j=WtKIdt zYS`rpX`jQ5>WWQplK6!uSe@lZSp7v`FY1-c(EYXUn~UM6sRuWfOC5E`Or0XEGn3MA zWJk*ms;u+pAQCRYmsu5C1x@D2jPrErK@Qe&L<+6;=XnW{13g)WB-M$z^u9;H>)|aE zkXtUoO-fIG(0)7BZVhsXS9`q-N=~{%chJ(zmpHw1j+>dCl=Q2v)%!EzETNjdy)As}!Y~8+rLGVELO-eEjrMuZ{T#{*bAtJw2^uy?l~IE4DRBO9m-= zM@!90(_7+;=TW|!d=M@nA;uh@AyY_j!77GFF?Mu610{XoLpIs5tt2>c=;j z|89oi-*xn#+XZt&L2*E_%|8k0dcZhrg#-C_IJh11xu43MlXnxmYs(B-Ve7K7zO`Ag zxF`KEP+JgNeP(URiErni3|U|>1I4@m-_9kr@B4%+_7OH7ZWleDtVs~!Y^q<~>};nV zli-mFS6;N7%Z2@pYEar9023cd`xCqZP1KtSu8*c4L0Q`UJ^*ACTeBX^M#<(Ch0 zAUCPoHyWBqJ-8OvsZpW3wxue~$|&SHn{GWm^Dps!y(n)=XX3Bq-`1uJ$ko#@Sb|VRng>Pd4+tuZsoy>olHyo;#71&6H-<) zrmr%BL9k>ZsVyjEjO-H<`q}N2c1zx)w2?1it{an^25ntl5oV-CBGIRXZi@Ei7LMW&(i&@b(#cZEs7VzH%Zc(QdW2AlLG=`^nTZ2$k8bmhBU4ER zQ|9hWHJ-anDzewWFvx^se2zwVcJy%l7vhY_tKkD=`N_^BIMKv`J;VU>id;?-!keLr zN$w?KD|lmxwN1*7->+9N191CqAYPd$> zM9z7iK$4!GSj;9`Upb8{jK|r`6rxNRYrzOf^s93ec1Lp>o-;;QGU6LA(&|cRBtMoq zSz5L)w494`d`4J z_`d;*w(W|`{mBI^0hCT6&NE}nHFbZb)s$%mXUpr1HF%3(@9F0$=W7^^5(!9w*ZlJzrNvKP5<}K^;I4(%R7(nGQ4I% zQ|J73tIbf){EdRLi&IAcu=r0X!~Urqa4oVz1yNQrp{D^%gckK+3PXN_MNTL|k7MKs zLZ1jv?oUq^$?u-5&loR&o-Byny}WGGLzeR2B`=*;R0f&SCcq4fR)ORcHU$Q;k+E4R zcF<^42XPogO=~$M*VuRnE~R6ru33<%qmVDdcx83C3)5EkhgAohmVkozac0pPdOhtr$5N6lSxs0dfvW)9f*wyj+ zhFq*!QO>jXS|+!OHgAe-+QW$2%txgaCJ_K~a?hG+b67D8H@VS~N_dOB6miG)p+qb9 zvNt+Ym9?~YfbJx7Q`Mp_yg1ACFi2CX8-{*JBo+{BJqJ#1kj8y17wHf*PA}3)XVc7Y z;;GNg7QHJSaRPm&q?H*4iMsI<4L33V5Cl6gaSJ0+l&HdiqK!m<$F?Ktecd0=^U1kr zx4MXEPFo9pi($ZIZgRw7D&W z6C6dIAWxyl=?%if-u>P#>!L3^6r9;jA;Z*J%H!l$1vh)Y?2TGQya zsu307FKFe_w6MfbN^%Vug6Xa8EcN-`rNooCXlb|A?ETX)T(}^UFU} zPW|=?E0HYslK}eW1mG1){11IX@jp$)|3%!WNCS?azO;i6`JzK`llc)AvY+V(fSxQt zs%Q_|5Ecvj>5!QdF(wKJ73@IqzrVlA=1E=BV-4?TaqN&5rDM&&m*cB2-Q?wWAN+vQbIpKq< z1O1+$H~~U2!SpA4ykLtyWG;%Y>i=Pak`fux&6E;(eEw&GqDzPS@JXDT1JXBX#)x03 zSspdMF!JjT>USkIjk3O!Vy+^PhzbJ?0g@~^)C9ByvO}#@3QB@hwVaH}W}6k^bCX5v z13bLg16~-^(u?ua(6z*5eLuiVx?PP(%of)c22H0YusHUJ;d^-6;jhpp=+ei)x;W3U z6i@iGFn3nvti^1~Bt^s&uYyW*?VbIvUr3IiRk?Q97w`FV8%s?^WFbyj#8*Nyubc2RJYl_IoKr!1^}%t9EvAPN1dFCb0n?r+^AU}$x*7{3Mi zJ(6Hwo!FjFyWAK>QMqN?nqS`rPX(#9kzAc>C*0puDP4-ch={rZB zT3m%jKQq&UZIKSQT^ww?E9hoWE222}4roghian06!?Ju$;*O?xl~G-juSV$CgM@Hp z7uj5SR}OaZx>Fz5tV!Lr!$;c9Ok6JAwzKhVISU}1Ku3!slOfRYewEcVu`!zJB0AqP zF}_{J6IJA6CkMB>7ng9aD!Bz#fv6+bQxyMBJ7-*0D_dC?MDCa;)?*irY6#8KRe88^ zXY3T9PC>igyVc$03U0!dx5WFN!PlfjrkYi&$L}$Mj?J{koqLvOt+T_WY3l(-MUx+Y z7a_kRa&36BShat@e#rm%>sPdMFt;)N_phJLPq2{v?nnP;=QEJQ&WLO}(2 zf4%-@moKE|fa`&rXu#{Y4Q8zMZR!LM`J|}sDzQfiOgcDdtJf@$GRKuGNyIqo5M)P_ zPO&dCG!oqOqgm|7Ov>j}IltvV*d%%{fkJXHnI-zjiU8J>wtz;sf_T`3wg3rCGbY6F zshF_OK)yt3SYJ?xYAc|-%RzEcOy)0{w&+4`jQL{!{IDq~Dz;ihX}Q{)_|(Rw0aElw60JKK4(!9rN<_D zl?Ngy^MG;h%>We&U=i;OtPO9bQS9rj`Y{YqUXdVx#DW*clZ6hz9XS4YHMMUJoQ#i% z5O0E+AW+llazdE!H~s-}e2h)9jrNNb!qkv&1ou3U*TPsC(9+2maU3%MaSiufibJDi zK*)&TtDo}5753NU#S)4cQ06iPGfiV@B1LeeP=%EDrlXgW=keD!?vW?g2w`2I z6Lyu~ziNmXggp%MSTlYk{Owl_+~hm1eewv`mkG;m1@&6n*R;CZBC?ifSXwcVqRZp? z+VbmjM|`U((p+IGDE$`GARoTEICI%$UZ=w&9NQznUPp?t-Ac;mc@A=Esba`De?`AM z4f$}>_lw)VA9IYc@I4${9M(Lr=v4K@Gf$oi(EVV zgjUehl#GP5T$R4!?i&4^G#nMWZs_$BQk`~E#&|utN$MI=v$SJ&upOI+BocES&bFb_ zYruF<#}nLFWXV|iBPGk?G*c#8sqpwMTN(EGADef7f5Ht~=N6a&2|)bVpFRoyAAiFC z`e-wV*g9D2J2?Sfu(Ff6mAR9-vE!c^-@2M6;0o?9YeI-1NT|=~w&6QP;*?ThdK^Vj z<+Bp(15gn&uBi!jkIK`fr^&!KSg?$kvnq~oWUI-ii8qE>E{~_rQJ+=_QYCn>&Dprw zpO8EV166uHKOaW;WzmIQ$rRWRF`?CbwKq!U>Qd8(xPv4<0#$z~1k#nG$n#UY1UWGg zq<&H2f~NhklVYShE z7TtmxkHZIcLepo^mMx_^bK|9alKa<6ONWiKXC^dWRaLI{y!Yy{b5+aT9h}Cx?Uicr zO9K!f*ILFcSu7tkY~;H!{n*$MA!;8w1Zk24-4-xzjQ=&Av0z|slQ2fSPD~EAqj6h> z*w7S^u-8~UELwe8rtyN;)6PD0?Xzrvh|A-^EDr*iZ7BWkh275x1l;axK5X2K$VAmK zm@m5qf3gd*6q?7}_lXvl_r6Cl0kS(s4fv;UQ%gYxfBRuV8gTO!ghNcDX3^x_})jrN=%*ahnX^ zvC!w>O{vBd$b+QT4|pp*^P_|8drWxj7W}`SK%dq~z0hD8dIK3Rl!b}S?5lzTVL!N! z5F(|N!B>AB5Wl|H;-R$9&WP2+UP$gCRc!7U`9YSizNfwpsE*w?WKPCPuixln|40|9fjZ>sZrW0yK+SfcDaTYJ z4y8A6*`Y*9#y{k#z01jZ4BHL-lsD0)|BfoTymD556LsKz3*WCk zB0u@1MnVz!=DH6wL|VdXL>7FR{1S&!@6YmBjBIIiV6PYU&W#l}xMw&C$$K|!OyA$) zk>||ser65VYFL!-PcwBtGA#==I3&)mNyTaGiY~#AJuEV92-G!iwx8g-(!TBTKHwz@ z<1u7Zh*n4^Y8dW;tS0Kq4_2zjJC2saroPJUU$C~kUu*YZn`uE0)q}BE!Xdz};5wbD z^RG;&`!(#goqvX1{bD2iZ48K%D?CTG7^Afp`hXcY#X)Hk?b0G$Q`#V(DZbjk@w##^ zndld(#_8Lh|3nb1yKu}z%d^;82(u#Jxq zXw8smM8OZd!EolR;f}JnDo$QkM1`-Ehj=GS#}+T1%w?_&{r9Q2TeGu9MmCNmZEl1` zJWydtg%sC?yjYvZoZX1RQZ{v~r^fn9Pfig7$anQRkDpzI@Sg3r==*1x5)1iM;g2t}Y`EFmbk zgGk{dzK?<8kqfNLI5=wSeZ#SO*AmfY*1N!^3rW1E183lj$N1#4apL?c>Tv6f(GF0!U~HtMZ(wEow-1#BVDW@O9I%@5*9wY; z_3s6}cU=6B?Jsu$YwQkKdVr*Bew@MMgd!KcX6cvG9AXW9Qb`K&`RnlaM;!9yBr^7E zP4EgVgaYPaPdBd%x3>IQ4-dCbvOpa647*fK@pd<7%eHiF`BO5XAs;v2`ao!e-;m1RR&+fQykk@-kZR+FgRh6_$(YWEsP zFYohZu-z&y%u0LitaC2!HnF9CfgBV{;fKzl*vU6z8+$Z5sK&1s-dzDo5XcA-!=Yh)*_vot#S zX+n3Y8#z}kh-lI|!6W|x6+}DzB*TjEOb5A`XiqR~*iRA;n>boQ=+wK*w_GmRV;7iF zNw_$=uEAT?_Fa!A=H!)SSj9Va@ILnJ0Z&^vMrn8<-L*HX$kl`!hUcaS!IadjeXqmWZuI9NP1hvXNIa%AveE#(d;oS_2ln=+_W?tOzi;O zptwNu-f=>5ce(^8IyHa`4Oe!kiTozoXv2JuBwz&4A?iC_>A0hkR!@%9 z(i}47w!^%`hzkD~Y3~>$3AiR$R~Nf%v&*(^+qP}nc6HgdjV{}^?dr0+zU(`@Gxu&x zd^@xAHzP74e`K8Z;du>p;3$Ecr7k+ zpixnn7^EI!>f)vOBOm39B`S2W6-$Kd1CCjlBuR0-8(9O-R!_P|{vht~mIWHMO}2aSBmG3kJ8lAlE*k(Gk7B_P~@)J zw7bHis_T31H&35pwdANLl>%ZUrEw}37nhQRmdfYnH|;@oCc5*iM#r~@g5jXs^gph} zv-#s+NH3AxVrsZ1W8-U!Z`h5KkMeFxL6Q3vDx-nB_w1!jjHa0JRI*)`qK_)aw{!cI zu|KIp_#u|dcPf}&Lg4PzI48Vo8o55V>)s7s&MH28KF{XcuYJ#-I6tAQ+*q{*lThv< z6VeJ*?{StG!z$uB21wg zG^(uhWh2N^O5?fv>29*$6*3XC&t61a@v}q()p3&n5=;mFXZ`~97FvW0iHtCfrOr4N zy}{7fFN_(OsOyu`S<5~rR3&`A%L|slBsb?c^WliKQLNV;-*9-lT4)ssSdVe|RJ6X_ zU;i}F`L|Rfw~FBj2@C|34k*|B*9SWP|6Ws;e}7GV6#FbU_z}9XKj4GpA{^Tq{$ETOJYMxspLEqe<OmJGXmCd8@&I9w_13#F@HCqCQt!FdP>E10dKZU;R+rL!_UJVxH$7$jI@bSIC z#35u52oI9dfKKfh69ZS(Y{(&>GKm@JzLXQl0Wy z){tWpgNQd-;k@oooBH?^YIlAWw*t|!M`WxaCxNJAg6fS1lZ0Y2%R_;Ad!5UXvryAL z=l+~8SM5trd-h{(+aN4dEP-{<5ZZ)7ez*u!z0@<}talceTB*6Y9I$Oel|B_Q*o-fU zk?o@{G;*xIq~XYDSEahlbS;%j4ZESF7pz8zOUQgmnxK(;Ok)=QKX3aJG+GA65xh9> z$C_-TQc13-36M%eOxfAL`ZpQGvlaMD2B5#5O*r>X{;4wbbCWT<%{DftllM(g>YTsIYJXq zS;`8LaeYAHLkzgt zq;fqdYHjeFVgX*M3^)d*u2~iK~Vux*TLs}hO*PJ)oBj4>r;2`j# z>$sJ;n70kYC*&bUEcM2erwiHs?r&9F*>0Q%2T_zExbS@5{h5W&dxBMIpe|#_Zs((4%g`7 zs6cwsez>v4lqp4gUUt^2e`dhlUOi!Y8HUmUBX{mktD4Y=8*mSu%hd|Zs*ulF%C8&u zdsZtB{G=b&gC?*~G`Fk>v|33J9X#bdS1==zv_m z{{6&}mot^Gg6tCvn%_-;Tlj5xQsvxbK!yg!Y8MOm5oY+&chSfRY|;9~E|Br|=0R3o zx~OaPG{sP=U>X0c17#p)1Ga{AyA$W}37T`S)c>}pqiPu(|`?h&_DN=AiQQms8`Hn2Um z*iRRjwVZ`QVe?j`d$;B2W^SAh?MsviaPh{UjazUVVqAE(3mTp22wu*g3d!CL-?QL1 zej878@nY|? zbYEHGcO`vIi@JZ1TymvHE3&tR%HyyR`7XbRBAKk&nG4cx*!tai$GU|n_A2+2XhGX(G6Ki7GHZz;XcM#v{kL`YK@N-PfNN{Vj>x(o}hG-+i zvUECMOpMLpth8ioHslk0lZ$%sn%MJ1l&QO1j_`3McENL;gBut^bjEY&^+qqcscjXH z5A&bZ-RRM~oB!h(DEatBCI+~nXmSduG5`9~7O}R)3y1h9D&30sh?NLwHNZ zdSRp}ol6K;^j^oWwN$-$v*4`YiOz5x9kRpQ-Ce)YAr=xbDLZh#>4AyEMuk5(OBW(Y+Ucn7e?0E|yiVAO4#mR1LS+;s~V1 zs7n6*hK^(2lBf7g9n#;SN2#@`eU8DHByBYur@RvFhk?g`5hvScxX<s6q&yIliBWir>l@aWptn2i#@LLx)YsXCqUchiTVfzQfe0ZljW@?ZL(X z=S5LlH0d)qa)1+`0LRauQSa>|rIsILU-`X)MZeyBhZgneYRl|DxO<5NXa1c?k2TZJ z5u#@_Y=;wze!BsY|N0xcmm?Yp$q1q`a+z8jh;IhJ7U?+7@4>dq=p5`$?88MQ>Ba*1 z*{@*Cg`Mva?Lh>)?4&n$7fPVv&=%)jkI(&XCg+zWg#9<^fNv2aeC2fh6{jR}FLwMf z=JqHe+gn@+$>^b(Ny5&C9b_9tZj-AXQmnj?=+Icb{$L{JOE%jz-e1>WsyXnCLMP~D zShQ250!Sg`mIS}a@_%W9(pDeu8G5%!{;U+X51d9swupjfLt;7fU$!z)lQ^9Y$ zDuk7pJQdwds&r05KpMEsd*91}iL<^oS7Wk7TN|4N)pNdV%!>}V85q)f@tjb*r;u&Y ztw0ttypWwQ|Q z4@2}&%+o_6RxLuV@PRa=e+lInfl;VqER&DBZk)Lo?9xRr$U{0hInmF^j6Iiz$n}6E zS$bd=!bprb7A3qN?dy@yNB%+e(oB8H9{!!+H*#(7KK$zg4IjHnT$IhIl+xGBi&@C9 zn;CtWu(d2p)hx4*mi)LH5EX@XR2Y^fc%~52pD(Gj5T=3tn>-yB=Gih$(LL1ZM6#S4 zIfD{lkQFVF~UfMq3Hzu8Te(<8eK@LdcBhODyy78Z%wX!p^zc_r{{!HE1 zG6IPRMd`-*?vZE%8@v-?M$OG$J8o8n3aw!#?)uS5@Y_-4(90X+@KA7djp_QXGNXc{ zlYdD$SMe|iM>89Y@8FIwk6ACvvl$#bZhIT#^{I)Arv!*43 z?}3&<%>QuH-AXf8d;ZZvtC8xdQfK^eJnSyvk8w5Ie{iry~$Cg?FI(##`k=$EPg%cjT+ zx2g%tE73rKcSO0I#F|)a|6O(y;>jWe#wGY+gSGabwI{{F6-+Pn|i}hO1%wU~mu9$Y$j+W~f0!{m<$NE%K&-GocL~oVsBo~u%VO5Wi zKw=O*1?Y*1knVqJ?{HxAZiP`ZW?Igw!A-_)Kn{ zGG_Jf?(@tRjrHRo8?hTi{%|bHNOxgi?kcxkWaF8F-rt)@C;EJ}v@;c3bI-s4Juc|| zjxKEp6WW-+y0zJD!RnVcMhUe%`?FwByE!2(S`KmKJHkOZ7SvJ?RIHlTGqhmb&>}BTz z8&82hZ92!Xk6$uARNWEFEKN3KO;H!)KTiyf`_jP%5W@m^0m+ zzK#QdmQX}%pZcA>KC`Ez1-G8{z~J#QZpsKRX5^*DU(Du?7&4ulS!wrWG4;gN7DxpV zeHSXu~O|jY`q#_-+Vsened& z>uHJ<171<$%KZ~>Ejjj5oJ%sOhl<6bPOFMLLp!($FGY{aZU46VuDD&5+I#tu*lOp7 z1L(QD{UW!k_|jK+y5v^?PS-jH-s;|UJ$uO*O>tjG_#(-=%>D@>OpS4?;qzNBl}8(| zIku4{8-GQuY@@dB+59Ln-7wnHWcs!@^mQ~AhgFpSC4wW4H9YZ=vKN9!thx%&%6{n4 z0@eB@A>C&o_fcBu-U5BEPgFs=#WSI%<>%yF-KJiMOB>RKGM{_j<_Km!%oaPhSPx$? zpTxQ|ZM3jAins^W8#h)z$)%`pNSmOoR3;9em7p&2=srQ6#~8IOna2;W8&VFFpWj=L z9P;Z&sE!ZHJKZTES7@ysDvb=wMS$}At+;tI(Sd#*%3_r*-#K5>q%x40u;TO5QTHQVa2VU@#K3oR0Do{s@ z&Ae-rO45(bG3CZhI2k%|V*Y$gwei=6C|}~=gNPa4IUifu^ZVSliZWz95?EN1Jb$AB z<3J0uWNB7=|KWZeY3Gou$Sux2(%Aaa`$~qti3O{RIQ&6-i)IbJFF>TZE}=Cocz2+$ z-<@fBOVJIcJn6Y%L049%bqY?Jb8&@`>`AQBcWTP|sdDMq$HQipD%f^VvZ2#7EHh)c zSK5Xh`ZXA|_M6}FUWWlz-m;0Og!uy}csbJ~Ra&T&k%{!#Fbuj>Q z$%r^~xC*x+sAKh4-E1=cV)KHjD$6&JIYqHL6EmoOKSOUVbf ztewTQxc#C;D}A-vM2TfO_DVC$y)IO&l=*g)j8eUX*rNlKj0|H*YG#XL68>tlh#0t4 zn+XqomO&u(ad9Z^O`U1{syn?In>CzL5ehp7)KZ?2X?s=gZejvP3jONQYp3&o$ih{F zqf(%GG}n$je$>P<8;E5{BMo95O2kJU6jDo`ox1_;smaR)e^Di!M?2Kg^CWa#2KwM$ zcz3HDL6@e)RCpCPtmHwh-q7RzT^jSgy9RiWVqKIlj~3?b^3x=6y5)r=6B!(8?u@b zus|#9#4KY=?Y!U2y}=6^2(#JEO@;Z`TLy+o$4d0{*&%|)C4at1K0Cfwaa;wO-c7uE5Dyy-0;$p*ka)-C}clC^y&u)o4r&2a`^UOA@k@q|c&Y?Dm>Qa0KlK+YpDzuNF}wvbSzk zQtF`Xgmt%E#7ZoGPNLnz=%qP5yr9W5#gaYLzWt3G>HMF6v_Cbh_P_&FpJ}O2H%FPfV~U8g#xmq&70DI3XFh232O+gDTm(d9Cnil){8Q z8dCwA@M&6h0u`iwBJzAgd}$Ot*rhue&0C~|%bQorFAEV~^PF*+0=gS4Yy7;ek=NNF zq%+N{Mf>>!(;yg+;a<}aoi|RrT+Cmi{@WkV9Jx4YyeCS`Rh#0xDOoc_P2YW{OJ`oK z$xnjTe@E`huR8I5wDX=6f>&hW?W#WhIq|Mw|4eq`Ws&xA=fMBpzhLHdQ|-A3@HH~# z`a|!Au$JWeH3=GaFYrCWAUgx@j~B)-Kr?NDd}j3W5p=Y@1eDa5JT0#S zz|9oc#D5h!Y=R$1^2>&&5S9H7GD7=e&z+X7;h~n4CUR&l@Yh6DymUL4P1h06=zG&9 zZUDXo1&8sMtH30nir{MK1H<#P3Z&xaD0L|N-PvV_w(bIXTJVc80E??CW#l=RCrOT% z2>oT-^-KaJhvBZbo4*ixPvo%p2~7`mRK^@8kFQ#tnA*8ZbAOP(3uT)!bk<6i&R{!) z%wF!MxeQ9O-+yo~Fwo+-Ah$*Qm-onyh+SUG%OG{7l8$XvWU`stqI%H{tMG5&+bhG5 zfQLxKX8xW$sGBG@b?KXzs4FG)^TKw#nWrIim06w2unU$7yL0BbIOV&iP4?(W`+2PE zwQzG)5wZD?c_^i3-4o9|4dmBp32$lG1Qe3wiX+SOM$9`?rn(vfluFJhrcWCJADKGX z70^mrg$$Kz=1G11xw@0*`LAl~9?u5R;#$YMnJjJVtL_I{l2FRZWK+#>P?cq*#7Ldg zHT!W(ZvR9H&ws3k|EG=9k?N;Gve(C4GQYmU{O9PuE47)xvn%&e;F_vYSzyz~XG-V9IJ=_Dnt0Zc;u_Lg_u@)KMrUZ6jN!u^WiL;E zqVUwRxi{6fUDhyi_!wEk;%_Wu%9gfl12$(rxA-8z<(Wyx=sv?U>Ph`ZSOw?ucHK7@ zRMI1PlebE6-SKfQtDS7xtnJo10Q=|Fb>f_`7M6~WntcwB}nh@%M8-mA-s6-v89Ij%TJe+lurq^@aKQS+_7 z3x}J{<{qpxBTN6HAS(yxhLqT44L^n_?_+saT9rEh?B1E61G&m(|ciXrp z3+@#HVrwTsZ3IA<$}|hSR{|S8X+1R=pyg{AjJDiv*`xndX$cBtPtW1{Hf* zD>?QV{cWwwzo~>vkpzz|N~wE)r`B=rG94ZPy}~N2PyZpt3&MFK)(F}p9F4oum{9=K zu7r7Lbsw`RpJ}8M-Bt~_j_o1&`}r3#;1`wULt6&6r$EyIi#yw{AT`xlNg6ap7dTBX z5JnMhHMPcKY%k(WRUq){m#dg^NhC7Mm2*{bnx_9a6MFo}-E6g2V0^=s9Lqiz6sp^t}BKh3c7B$GA<4M?(o**fkG&&dD+XugX zQB&`o;a1cnY*0rLaI(~a)@T1IlopyV*Ue96?p32dR3oDM(ce@wI|<921<~Y@y=o<9 zCp8t+K#RsJONUaLVHq($CO_eSk+vd@j#WJ9h2QoZ;D!IP{n8s#6`E1MjG6XpxSEy1$SW#K(L2AXpZD@5l+T zL<1bW?&IFhn<~rV1PdDL$j`v#$1i?V(8Mp^x*?w$lFnObu(dXYP{8~N3BBFfVzSb5 zxplU2j`!y{aD;=6FU`a!D7Fo|1)}}@O&$j5h)AJ|SPGvxD<|s%yb%IwAaL*{d{B@sqR5^?G6!J_lnnu* z)0E*TlGI;FIk3iHNgSV7sT={Mv=7pGDp;0f@hqEzh)O|FR<$=IR8gU+AB9?7G=O)g zX||VrkdTg1)Lq(O>>=n;c?~iv<$XLd%_IBr zfidUkrZr0&oEZAS={`pLN*h;>LNWimpCl>6!z+|{z@Z_d*f^#}U_8H~go8A+kS|5L zDfd-SMU!(VQc08Xy`tA!b$J2!2C}?Be?C(*K{Tg5Z*+gz&7?P^89tdC(+gvkY}kQ@ zJ7S+PRN>f*4?8rOk#}eC-V0t$|J^&UyfQq`9N^?Oc|0Z4_R})c&BSCuO1$zz40IIbW9f7iRdGg#P{yB3HVYywg^knTVGw1nYDUm1@V}REN-GJ9 zvm^^bU6Rv&wZV$&QdvINTi%Vm9w;W;J z6Z%zfwF?KQ-PXkJMm$15{6!cYnw`!?^vHA;#eiev8myiHs5S9OxTfaRasW6pq=Z{x zb{z2!%O7c`>dPke)2B)5GFlbGfzx$Bo354RV+-^>!Wi8wD z1s;I5^q^bo1|HORacAt!-4h$@=b?jbKLiuvLvD-7cPo7< z+uCAjr3-aH+w%E@#;)_m)B!7zDXG4nxkyhEeP;)@%K?e9G~yUkpA+)m;ue&DBuLzKVL07HMM zuHfEN$#M#klQQ{D=rN3`HGXJVLHS{;zo3xb7w*kn#pRb>W}K<);4sz*UOt<9#)(iUn3CQnf1!W zZq|nzTK`?GIbWr5W$>Jw6vihVv9(I$CwHJFZFyD8@DyFxaM!Ttd`mf3MC)7Go>t|D zv_1_Z>yf>44EU5zy$Fzm3x!8WMV!scGw#2#QrbFdeht7%4FD@8{+k`Ge;aD}cOmcp z2}~`(SSpGyeEgTa{zD%e4!|3!S}SBjcDBjsY6|d1D$mZ>5BxhYxrmRVsKF#UN(}@F zME2XgPq@(Mvy%>p*uPq*I z*41%YqO}Je0sotBDRH3K|1!U5}?)<3u-dW2kKGSwyC!W zplf>yF|3H*dDu#R*yJHWyaNvsAkUtL(8FNQ-h>R)T}^Gmn*EZqHM3vIl=V7TyJZX> zLjg~^8?tB30<1kkc^=T+TCn$+gCKbwLgF)-6#knyQotx&J+M9=@2@x#8c)IBFujqa zUy(Nt3FY6!kv{?A$nJcAII_)gZs|0uarzF?;m_1M;c}2O519ilwL+euXazwc!@O4S zR=-F5yqBPelechMF=JkJ&?%%1EzF*gL_Bs5D20erjpOv zgTzL(yaAkXYysV3h!GYC3`J=eIdwy;Z>rL{mYwvjl9_k@ifP4r8rgQaRuiB9jt zhO`lpSD#TlZF$DR7OIJ@RMaG)US2QjEatbe>l@k&s~D{L7Ue9u`!T!t*r!S#)K-F4(@^=fR5!m6ON zeX{m?ADg}eW9c69>~{sz;fK~^S3G97{me=SrBkq9%hD!nK znr{o4+23}O;@iVW7ZZx=AIzy$f0anRz>S1#y^P~alEMvTS7$dXGAx)jeLcZ}){G-f zK^3czR;>iRrByQ#dhkUimhu;_J=!&HPWMgOY>lVSVwQ%XwL|1|=+SB_qmWjPszC ztw3u)tkhFJYnp4Wn}yLR%&{lkVfp*Z^Z~9uXfm|*utl4@}}lh zG14Zj^81zQVNDnyzhH+*5g(&X=a!8lMe~&~Etln*;{!+?KHEU6sNUB)FcfJzh@`V2 zHLvgwOC_}BMwJ?+b8-BxAYTl->W^8QkW=h|^0jC+t2R~$U;MB|zHyBg|Ilde4AaY5U7`L+NO^zSbi2Bra0;mR41)5gJd$F3@(6%HRzM^Z5b zXg?D`hyVtQpFT?ZEeF@r**n=N<}l`6 zGwmgd=wNlxqaxM<$zWPR^Swwh&Soh@zm_*0)1!MAHC6c;*i`RDY}p>H$`ZkSKosL8 zFr)zji*MS}{RB8F^tnN=8*5uQymGd7WD6elsQs5{v}OxzecWj>XJ=TX3v{=9KC8FsMw^4a-cB^Zxb*AlnO})!s$GOA;*c$AO#EXA%g+k1|X=bTg1ePwLelsZT>6z6(TjMvs3 znSPK-)2xR<`v9kIO+xfazMv=(1-3^R$vfU4GIN&!@-%MJ0)hLHYTPm2c=y^w!Mf;lyy{GW?SN=Yjn{HWZ0}$CQ`*1>v%I2sCuge*Q#bd zE$=s>ZcwaB2OY+0>vV0sNl=^B7mv=yPO)SKHD$NA?(T$b(bvjuVD6H%CJo9WkAxpx zoK;>ov(jr9S&^@9)1cLw(L41J$3R_s*IUWOr!L*+vUDb-QyHw+RPk-spF7x1!1Jwi z(Ia#vjb~>Mq}-pMB4J7#@66O!6~A$0pPBP+VzpPL*Z`A-Imuza0(+>Y{5uW{Rhe~L z?C)F`o!{7-v54$mKtXyy?VPT>J_|UjBp>%geR3&cNYwV-zdJ;s@}uu=w1|6o7H#O8 zY;Lavwwhf(;fx%ymO2(=Y)92$?k8&gN?&h247aXr5;Ah_gHZ)*&(EcWt%pU;T`1BP zC5*dM({dg&q8$7d+=A)Z&Ftni0*Ru`$1a`+PwkXsdKw0ma#L6JtFIS-_CmK!MkDZL z?D~UaFGTZ$?xW@wyWu12_Tiu7y}!JoSza412Fy)+0@mC${-1gEccfLw&f3MsR@%bJ z`9DQgii(Wg0qegxFEG61fyG>%EHho}Ti7g`U5-Q!ojb)eu_mlZ6r~guq6xpcg%o0m zC*DOs5s9a}JnoMZa~;h5KO_M&Jf3{%hLqgl8VLC_7qo9 zQdXXUnh}bYwXH3sVBzfKdt1vN4%18OCj-usw_rm}Hf>(5V=8@crz@)*HDIH|0gOtSunLcu0&X!tVu$lV%DCF}Raq`k(LT2C(?1&(DqaxSOJN z9brS1-q=+^D&lr-^w50$_yRAkFyiM5B;J(CSAk`YmDHp$(TIj|!>WLl_ue!+4{6xQ zCSwXgN_+*#b7&}KjuqGO3~^F8@&gXGW}Sz+&W_c?k7(wv6~lyc-<}=$wkIW&vb2Qp zIFrDK<9pA8^_AR)EL2|8v_krfOTbm~%VNe`crRmL3-@D)VG}nuxq-&O_rKGq+u{cy zljGW(-a@K`PG1x=AL$my_dF6--i)m^AvY55Tr)ik7wRp&JU2z->Gh)C1lgkrrzlz4 zoJK2O+jaAo=7%@-ogp3;jLLMGuDVB|(QppKqg+lUa~3Vcg{+6ZT(bmGm?#mUYoXec zh6}8-!yjglt3j(kewg!}b&#{vI*B)3Z%Fx%-u#}8gj$q2`tUCbzd_X#nd8^3*7ya; z6mcRSC7lD)W>Gy})DYBNdc24jNw$pX)4QP5_Eg%UYkb{Zb`4Xd9?GAhw78?@dScue zvG759=k{?6Yp!I3K-hfR0|z_X+S<<0;)>~+A+S5+UlY=PD%~$RQNNENBBGpi9j5bi zdoD2Vynht@(g`bkp14)+2Di0*1^0o`YPJ@lIG$MAB(d5bp9*j-)o*V6g_N^(?Au9hPraPSw2UjlLRJ?=+aPL9{cn%{oV)a-l|t=E6bv$y2kKleojE z{phvTL&p-t5vQ(SZVE-MjZo>moT~SkX5Zj@miRtAt4W>bsw z1MwkDD|1#@Zt7Wn{+g^X;-j~GcMIPG_}-8FxOMi#6c_V{kJ{6 zyVT`VJ`dJ{-%(M^X` zL$K&)pw5NGAd+pYk#>>`3pe~J%%|Y-fzrL^XaWc^`n*wr=KK2FfK6yMcq@0l&R@A9 z7rU&1OFY!7dl&k+Rf3vZebgU7eqehSkObvoDYxbFEzkwy)eULPjH2N@SXyW1XTU~1 zM+_|F^NGdZ%e{q3%IL`DkF+-^tO(QD^P*2S7hUHDuFnk@?wRI4_@YEA-d}x%_SWV8 z=7f}dKOyJGPacPxYxzt$sJtiX#SEC&PClYnrA&79o<=|BZztiSC$6t^Le0RQK@5_c zx)X+>(^J~pUSq3-kN+s;yfQ6Jo`@wbzZl!sQ%E!SHIcdfS(9hd-cK|hFQO5h@~EK)%FOVdhil-YbMa3%GE)9kb3}AOJIp# zHCyN9AydE&d6IAnNS{V>e{g-T;@s&*Oi#3BOq10MuDoT`7ER^rX1A}8`wIuNR(G^Q z9RM6MZ~$-^;1bo@$P5LyeRBkhV8e^E>liYkfSKwWrZx5@E;(BCe#DvZbrc2_;iU60 zm8;!mo_gl>`b-|!d$)0~(FJB}_Alkqs5zzur1b{RylfE5Y*)6;jeP$b3=|ZzxcXN~ zu-S!yRi{3$1nN+TTU7P+f;}4)CH2F&isfhD)hc$pc}lL>{(|99ZuOtRz;uV?+rz0* z+`Qda?dqHTKGKhI2EN|p6j(0W=-gZrOO&%=5_cTGAHNsB)q3hu2|w;q^@o;9$u`E= zk72uE->MagbUQUT6Q-Io%k<{=DeFQ`8BzVIh+pnM?Jxf&130?p{UCr0JO3jx2-&&V zItzOIuR-YlG-@bT*{}sf4gW}VzC%~xusddy76=5WbV&dbosH2AXF#Gu-1s-qF~lDF zo9GD7uS+0OBM!#1r!tvMN1K|JlG%gPs~zdydmHWj-rx69w?XJnBzZutoU~0BZBt2+ zPCt_5OdY<8B_oF|;a4l`d$PTnLirnhpkz6 zZh=<~mgPQaE2C0Cxx2cJYFrp;P*a# z+SEnZ7^rUydbGWxRp%T9{qLeBSn4H% z!Dig~z$Uu&I6u_n%1D;LNX`SXS4@Nm7D(fF!CITOCkb2@+@M@J*z?RB0(v06eh{=4W_`oiei#phJ4 zLR=l}t5RxWhPgrsct6WoFiDHt#>U455PNxRfFAsrToy>vi1MPwFFYkqy$*5wpNsBO zN;qJ?irip7OKijsp3U=!rzT=Y6(R!=lT4*3UlECIA#QwT^u-@1`4Fa<*2oTfAWIn<5!{^e9HIYSnySC(4 zy+}&HiM%h{*~`>~PBRE3zPb#BXu+9ox%xi5X?Qo|tS}psQ1m2$9+mRGnjw!iQSOEd z!s)=D@?1txkrl#x?r2P(x*2C*<94prT~3 zHSz;LNMV-|QDt4`Bq6~ZR=0LFuUja6BgW4mYq(G`D#HYuFLFoyERvIxCdclw$Szu>GTW(f9hFgdhyBsxG5ZIV2>*vR;O{nN7MUv#Xo+v$`7(BTR|hvxrt z!XXSOl{lOH-`Jt^H{u~?k(9m<;Isqt&)G3*2`W9o1eJN!+ z<3x%xh0HpSoII9vK#P3P)xvr<=10W3Je>9$`fj_wL?=tSE(?K|ia_5JK}yItLB2f* zCi?d_sk)|K65|dk5^H)|0{RnRjY1ED)?*%9`?rM?7_jL!=hc@jx2^3;lM{^~Ujp z9ZTExNi%&-8tlAe?8?`U2BJ^SilRPxe-vXRQUMqP?tlvdxC0H4dyE=iU0>ZkquW~q z;mTXq&?6A)pK~&8P^pMKTLK6^0eSMtWA^K>3j{8%0I)dU)<76Cx z1DE@a%zOsZ77l%`U--{C4`+M;JMs$;RFf_i?q+bGaRBTXakc7S7>g!dvOMyZy>D?G zklt#hQ;r;)XGx`hELjl3`-%dy7=YrGq0@fWGg@TSxRTc%1+5mr84K}EN9o$9z6K7DNbVHs6r0WSI5Xod7I9mE^qnBbszlt)w$XUY6~ zSlv<(-uWm=PX#Rxh>&RO;8U8q>>IRktwhX-)JF6hc=iEwP_I6f4-KGdmljTO4RRdJ zw&~qK#cp~gcj~;OjjeQRIx}zr8)ybxVy86NUhQAZAg>|0L11&yXC}(eT z{jIm{cdItfT-wsWLnIK0WUV9s4|lHz<~adu^lvu>}!+&(||MTbq;Nkp_ znnXN^n5+{etGd1onZ=UK)uLm^77pMXQL}Vv4b^WW;0wAmWF}DsG%S*58g)Q1!rg z3gTZx!2AOdutAO%^j(zvaFjv8xcrpR=>md#;H=sNyGFs~V6;CJB`DdG5c_jBbaKiE z@1T?ENFp`0M88D~DtfLnw*oh^xVc?b$?U|9ynk++aoFjdU8$pVPQB2kZA}hjI_>L@ z@Q4Qt`w!P*t|-5~0a24UB5EO<^gZP<*Hw#Z{$+%fZTn_yZ?Y!ZKMJWXrdn?*$`V1x z;QwAol_oPlh=od<={sK;8i3-J`#CY@jk+0Jr`~VP@C#10&rnvbl|J1sK(6n@6BJOF z035{y#20@dF$~af8b%F^qBcoKBJSLVLnUuS+aR`_V_QnN2t;!34ZEx%jI{wFaqqFV zMxCjql40lO#2@={Q7dlA!C9@_e$YrRPEuZpQHpy0_UN%c%d90dD31e1PF{}pk(CSY zo`1pw`sv6QuSzwNqnt&NK=S(>RiR$;V?_7`S<7{oMu5t@i4AP5HTW|nTul@g8X4tT zs~FiddkK#k{g8v287micdFso@IDJb&$!}l^yd)j9EEi2jtbs)Xldx|TcZIll=xk5- zKKN{aj5`_Bue>ZifqHyZ-q}ND*;o^8ts}$po-a0LL)p{=a|gR44{F2Mn1wDE+u5gf zmX~%kB4cC~_^ZSnhB{VC{9q}Xpje2!60cd2nU%rf$#?^vz+uPz26jJ-b&3unZf6Sp z{{B_R{m(*YWNc@odhR?Q$EXwiqf&Qk2RJugw7Kr0uTFb{piiq#z96R-M>fGz=m2dB z6myaHbvWSMUEnO!%4(%&wq5UqO#7tyq{qOxi+btw4{{5o7VT$MxcO@I)?p1?MQ=;f zZFznHqLVQF(#c&UqT&PEORaTA^U}glZX#>G?!DUziy(0cDY8Mttn$OrwOG;DWvcMz zpr~aTCfdyh=8O4=>XmB2sf=R@$&va7a_c6^ypgi4a9ssErXO&A#?rHgbb2%8tB~nJ znmO^4QxDB;OA-#w*aNeL&Z?*%P7AD+I#eX_?X}v{A+{JC`2knFLb`6rtzGgxo;xh! ztyVTxZ~AZ9_Uk+l>sB0p-F4b!$-ddVV!84e9_YGc zb76t(>KbcZOD`XYzM0%}N$I`e7-~;PDERex%p2W2PoKRVtW-7P3C4JiV}E}BABPW| zXhMBn0QM$$hW`np{#V+gW^UqWB4lmg;$-rlGU`eb;42qL`G>EZFu{`25-CTu8ekiA zmdgD9SbN9!%KL50yJE9qt70b=+ZEfkZ9A#hwr$%^#kQSP?4(!S_vt=+@27h|*LBYM z57wLY`OWVfbBqyGHf>x^ju5~dv+|wk*904A<;&J%6mLx=Z;hX$28}YZKG)-~REMc` zOr7@kwUr=NS1S=+=5{@a*(vmnRURVlhy?tI)oyq_J06tmk24GA`0Qr>{1G0 z);+B|ksG7&!<1dVWeM;aZy#tJ2g#s-gTRu~W=O?LAt^IBd#zI(bXhi|hX?)iS|>%X zZ~EGhbW!eoWl!Jc3AAj`PB%d)PsD%8O{sev|E-VKxBfRM0jH~93!f_~q^5#qfDU9C zd3s|EY%46ziXtUHS(f-UIzJeE9Goxzgls;iz`GoXmZRvq9F?uZ27WibH)j6X<t(;D^ABn^lLv*MyKFLFY8?`uj`rs=yE{TNIuma`4`HC31rR!J0UUXp#+GU z0tsr4LNwTzNiHs8(;@s&U3%JmWQJmSQ8i#OPTT!ycBL*&LuW^ClZ!p#?KhhX7**Dz zaVX~G!w7n!n%%yJ7OCxtf{&mmimOa^XQ|y7c0F-_"x-009hHWHP#Lm0utY7N}O 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