From 12d6332d6d074c02c5a5af2a2dc73c25a4378aa3 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 16 May 2020 14:49:16 +0800 Subject: [PATCH] =?UTF-8?q?0.2.1=20=E5=A2=9E=E5=8A=A0gaea.app=20gaea.mongo?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 30 +-- settings.gradle | 6 +- src/gaea.app/build.gradle | 18 ++ .../com/synebula/gaea/app/IApplication.kt | 51 +++++ .../com/synebula/gaea/app/ICommandApp.kt | 56 +++++ .../kotlin/com/synebula/gaea/app/ILogin.kt | 15 ++ .../kotlin/com/synebula/gaea/app/IQueryApp.kt | 62 ++++++ .../gaea/app/components/HttpMessage.kt | 12 ++ .../specifications/NotSpecification.kt | 24 --- src/{gaea.domain => gaea.mongo}/build.gradle | 7 +- .../com/synebula/gaea/query/MongoQuery.kt | 133 ++++++++++++ .../gaea/repository/MongoRepository.kt | 35 +++ src/gaea/build.gradle | 6 +- .../com/synebula/gaea/data/message/Message.kt | 36 +++- .../com/synebula/gaea/data/message/Status.kt | 18 ++ .../gaea/data/message/http/HttpMessage.kt | 37 ---- .../gaea/data/message/http/HttpStatus.kt | 36 ---- .../gaea/domain/model/AggregateRoot.kt | 0 .../com/synebula/gaea/domain/model/Entity.kt | 0 .../gaea/domain/model/IAggregateRoot.kt | 0 .../com/synebula/gaea/domain/model/IEntity.kt | 0 .../com/synebula/gaea/domain/model/IValue.kt | 0 .../model/complex/ComplexAggregateRoot.kt | 0 .../domain/model/complex/ComplexEntity.kt | 0 .../model/complex/IComplexAggregateRoot.kt | 0 .../domain/model/complex/IComplexEntity.kt | 0 .../domain/repository/IComplexRepository.kt | 0 .../gaea/domain/repository/IRepository.kt | 0 .../domain/repository/ITypedRepository.kt | 6 +- .../domain/repository/context/IContext.kt | 0 .../domain/repository/context/IUnitOfWork.kt | 0 .../specifications/AndNotSpecification.kt | 0 .../specifications/AndSpecification.kt | 0 .../specifications/AnySpecification.kt | 0 .../specifications/CompositeSpecification.kt | 0 .../specifications/ICompositeSpecification.kt | 0 .../specifications/ISpecification.kt | 0 .../specifications/NoneSpecification.kt | 0 .../specifications/NotSpecification.kt | 19 ++ .../specifications/OrNotSpecification.kt | 0 .../specifications/OrSpecification.kt | 0 .../specifications/Specification.kt | 0 .../synebula/gaea/domain/service/Command.kt | 0 .../gaea/domain/service/ComplexService.kt | 6 +- .../synebula/gaea/domain/service/ICommand.kt | 0 .../gaea/domain/service/IComplexService.kt | 4 +- .../synebula/gaea/domain/service/IService.kt | 4 +- .../synebula/gaea/domain/service/Service.kt | 6 +- .../gaea/io/scan/ClassLoaderContext.kt | 23 ++ .../com/synebula/gaea/io/scan/ClassPath.kt | 49 +++++ .../com/synebula/gaea/io/scan/ClassScanner.kt | 202 ++++++++++++++++++ .../com/synebula/gaea/io/scan/IClassFilter.kt | 11 + .../com/synebula/gaea/query/IComplexQuery.kt | 42 ++++ .../kotlin/com/synebula/gaea/query/IQuery.kt | 42 ++++ .../com/synebula/gaea/query/OrderType.kt | 20 ++ .../com/synebula/gaea/query/PagingData.kt | 67 ++++++ .../com/synebula/gaea/query/PagingParam.kt | 44 ++++ 57 files changed, 992 insertions(+), 135 deletions(-) create mode 100644 src/gaea.app/build.gradle create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ICommandApp.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ILogin.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IQueryApp.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/components/HttpMessage.kt delete mode 100644 src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt rename src/{gaea.domain => gaea.mongo}/build.gradle (56%) create mode 100644 src/gaea.mongo/src/main/kotlin/com/synebula/gaea/query/MongoQuery.kt create mode 100644 src/gaea.mongo/src/main/kotlin/com/synebula/gaea/repository/MongoRepository.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt delete mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpMessage.kt delete mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpStatus.kt rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/AggregateRoot.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/Entity.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/IAggregateRoot.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/IEntity.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/IValue.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexAggregateRoot.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexEntity.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexAggregateRoot.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexEntity.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/IComplexRepository.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt (84%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/context/IContext.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/context/IUnitOfWork.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndNotSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AnySpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/CompositeSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ICompositeSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ISpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NoneSpecification.kt (100%) create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrNotSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrSpecification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/Specification.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt (89%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/ICommand.kt (100%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt (70%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt (80%) rename src/{gaea.domain => gaea}/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt (89%) create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassLoaderContext.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/IClassFilter.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/query/IComplexQuery.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/query/OrderType.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingData.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingParam.kt diff --git a/build.gradle b/build.gradle index 573de26..8a84dbc 100644 --- a/build.gradle +++ b/build.gradle @@ -15,31 +15,31 @@ buildscript { } allprojects { + group 'com.synebula' + version version +} + +subprojects { ext { - version '0.2.0' + version '0.2.1' + spring_version = "2.0.0.RELEASE" } - group 'com.synebula' - version project.version - - apply plugin: 'idea' + buildscript { + repositories { + mavenLocal() + maven { url 'http://maven.aliyuMongoRepositoryn.com/nexus/content/groups/public/' } + mavenCentral() + } + } repositories { mavenLocal() maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } mavenCentral() } -} - -subprojects { - buildscript { - repositories { - mavenLocal() - maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } - mavenCentral() - } - } + apply plugin: 'idea' apply plugin: 'java' apply plugin: 'kotlin' apply plugin: 'maven' diff --git a/settings.gradle b/settings.gradle index a8d3942..b6ccfa2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,8 @@ rootProject.name = 'gaea.project' include 'src:gaea' findProject(':src:gaea')?.name = 'gaea' -include 'src:gaea.domain' -findProject(':src:gaea.domain')?.name = 'gaea.domain' +include 'src:gaea.app' +findProject(':src:gaea.app')?.name = 'gaea.app' +include 'src:gaea.mongo' +findProject(':src:gaea.mongo')?.name = 'gaea.mongo' diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle new file mode 100644 index 0000000..7bd8649 --- /dev/null +++ b/src/gaea.app/build.gradle @@ -0,0 +1,18 @@ +dependencies { + compile project(":src:gaea") + compile("org.springframework.boot:spring-boot-starter-web:$spring_version") + compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' + compile group: 'net.sf.dozer', name: 'dozer', version: '5.5.1' +} + +publishing { + publications { + mavenJava(MavenPublication) { + group 'com.synebula' + artifactId 'gaea.app' + version "$version" + from components.java + } + } +} + diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt new file mode 100644 index 0000000..9ef43fb --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IApplication.kt @@ -0,0 +1,51 @@ +package com.synebula.gaea.app + +import com.synebula.gaea.app.components.HttpMessage +import com.synebula.gaea.data.message.Status +import com.synebula.gaea.log.ILogger + +interface IApplication { + + /** + * 业务名称 + */ + var name: String + + /** + * 日志组件 + */ + var logger: ILogger + + + /** + * 安全执行 + */ + fun safeExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage { + val msg = HttpMessage(Status.Success) + try { + process(msg) + logger.debug("$name business execute success") + } catch (ex: Exception) { + msg.status = Status.Error + msg.message = if (error.isEmpty()) ex.message ?: "" else error + msg.data = ex.message + logger.error(ex, "$error: ${ex.message}") + } + return msg + } + + /** + * 可抛出自定义异常信息的安全controller实现了异常捕获和消息组成。 + */ + fun throwExecute(error: String, process: ((msg: HttpMessage) -> Unit)): HttpMessage { + val msg = HttpMessage(Status.Success) + try { + process(msg) + logger.debug("$name business execute success") + } catch (ex: Exception) { + logger.error(ex, "$error。异常消息将抛出!: ${ex.message}") + throw RuntimeException(error, ex) + } + return msg + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ICommandApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ICommandApp.kt new file mode 100644 index 0000000..c6bc4e3 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ICommandApp.kt @@ -0,0 +1,56 @@ +package com.synebula.gaea.app + +import com.synebula.gaea.app.components.HttpMessage +import com.synebula.gaea.data.message.Status +import com.synebula.gaea.domain.service.ICommand +import com.synebula.gaea.domain.service.IService +import org.springframework.web.bind.annotation.* + +/** + * 应用类接口,提供向Command服务的接口 + * + * @author alex + * @version 0.1 + * @since 2018 18-2-8 + */ +interface ICommandApp : IApplication { + + var service: IService? + + @PostMapping + fun add(@RequestBody command: TCommand): HttpMessage { + return this.throwExecute("${this.name}添加失败") { + if (this.service != null) { + val msg = this.service!!.add(command) + it.load(msg) + } else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } + + @DeleteMapping("/{key:.+}") + fun remove(@PathVariable key: TKey): HttpMessage { + return this.throwExecute("${this.name}删除失败") { + if (this.service != null) + it.data = this.service!!.remove(key) + else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } + + @PutMapping("/{key:.+}") + fun update(@PathVariable key: TKey, @RequestBody command: TCommand): HttpMessage { + return this.throwExecute("${this.name}更新失败") { + if (this.service != null) + this.service!!.update(key, command) + else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ILogin.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ILogin.kt new file mode 100644 index 0000000..22a30ff --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/ILogin.kt @@ -0,0 +1,15 @@ +package com.synebula.gaea.app + +import com.synebula.gaea.data.message.Message + + +interface ILogin { + /** + * 定义登录方法。 + * + * @param name 登录名 + * @param password 登录密码 + * @return StatusMessage, data 内容为 map 其中 key account中存储用户账户名称 + */ + fun login(name: String, password: String): Message +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IQueryApp.kt new file mode 100644 index 0000000..dc70075 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/IQueryApp.kt @@ -0,0 +1,62 @@ +package com.synebula.gaea.app + +import com.synebula.gaea.app.components.HttpMessage +import com.synebula.gaea.data.message.Status +import com.synebula.gaea.query.IQuery +import com.synebula.gaea.query.PagingParam +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestParam + +/** + * 应用类接口,提供向Query服务的接口 + * + * @author alex + * @version 0.1 + * @since 2018 18-2-8 + */ +interface IQueryApp : IApplication { + /** + * 查询服务 + */ + var query: IQuery? + + @GetMapping("/{key:.+}") + fun get(@PathVariable key: TKey): HttpMessage { + return this.safeExecute("${this.name}获取数据失败") { + if (this.query != null) + it.data = this.query!!.get(key) + else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } + + @GetMapping + fun list(@RequestParam parameters: MutableMap): HttpMessage { + return this.safeExecute("${this.name}获取数据失败") { + if (this.query != null) + it.data = this.query!!.list(parameters) + else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } + + @GetMapping("/split/{size}/pages/{page}") + fun paging(@PathVariable page: Int, @PathVariable size: Int, @RequestParam parameters: MutableMap): HttpMessage { + return this.safeExecute("${this.name}获取分页数据失败") { + if (this.query != null) { + val params = PagingParam(page, size) + params.parameters = parameters + it.data = this.query!!.paging(params) + } else { + it.status = Status.Error + it.message = "没有对应服务,无法执行该操作" + } + } + } + +} diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/components/HttpMessage.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/components/HttpMessage.kt new file mode 100644 index 0000000..2f50073 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/components/HttpMessage.kt @@ -0,0 +1,12 @@ +package com.synebula.gaea.app.components + +import com.synebula.gaea.data.message.Status +import com.synebula.gaea.data.message.Message + +class HttpMessage(status: Int = Status.Success) : Message(status) { + fun load(msg: Message<*>) { + this.status = msg.status + this.message = msg.message + this.data = msg.data + } +} \ No newline at end of file diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt b/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt deleted file mode 100644 index a6a28fd..0000000 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.synebula.gaea.domain.repository.specifications - -/** - * 逆反规约。 - * - * @author alex - * - * @param - * 规约对象的类型。 - */ -class NotSpecification -/** - * 构造一个新的逆反规约对象。 - * - * @param specification - * 需要逆反的规约对象。 - */ -(private val spec: ISpecification) : Specification() { - - override fun isSatisfiedBy(obj: T): Boolean { - return !spec.isSatisfiedBy(obj) - } - -} diff --git a/src/gaea.domain/build.gradle b/src/gaea.mongo/build.gradle similarity index 56% rename from src/gaea.domain/build.gradle rename to src/gaea.mongo/build.gradle index 62e020e..c196825 100644 --- a/src/gaea.domain/build.gradle +++ b/src/gaea.mongo/build.gradle @@ -1,14 +1,15 @@ dependencies { compile project(":src:gaea") + compile("org.springframework.boot:spring-boot-starter-data-mongodb:$spring_version") } publishing { publications { mavenJava(MavenPublication) { group 'com.synebula' - artifactId 'gaea.domain' - version project.version + artifactId 'gaea.mongo' + version "$version" from components.java } } -} +} \ No newline at end of file diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/query/MongoQuery.kt b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/query/MongoQuery.kt new file mode 100644 index 0000000..85206bf --- /dev/null +++ b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/query/MongoQuery.kt @@ -0,0 +1,133 @@ +package com.synebula.gaea.query + +import org.springframework.data.domain.Sort +import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.data.mongodb.core.query.Query +import org.springframework.data.mongodb.core.query.isEqualTo +import java.lang.reflect.Field +import java.lang.reflect.ParameterizedType + + +open class MongoQuery(var collection: String, var repo: MongoTemplate) : IQuery { + + + @Suppress("UNCHECKED_CAST") + protected val viewClass: Class = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class + + private val _systemClass = arrayOf( + "String", + "Date", + "Int", + "Double", + "Float", + "BigDecimal", + "Decimal") + + + override fun list(params: Map?): List { + val viewFields = this.viewFields() + val query = Query() + this.where(query, params) + this.select(query, viewFields.toTypedArray()) + return this.repo.find(query, this.viewClass, this.collection) + } + + override fun count(params: Map?): Int { + val query = Query() + return this.repo.count(where(query, params), this.collection).toInt() + } + + override fun paging(params: PagingParam): PagingData { + val viewFields = this.viewFields() + val result = PagingData(1, 10) + result.size = params.size + result.page = params.page + val query = Query() + this.where(query, params.parameters) + result.total = this.repo.count(query, this.collection).toInt() + this.select(query, viewFields.toTypedArray()) + query.with(order(params.orderBy)) + query.skip(params.index).limit(params.size) + result.data = this.repo.find(query, this.viewClass, this.collection) + return result + } + + override fun get(key: String): TView? { + return this.repo.findOne(Query.query(Criteria.where("_id").isEqualTo(key)) + , this.viewClass, this.collection) + } + + protected fun viewFields(): List { + return traversalFields(viewClass.declaredFields) + } + + private fun traversalFields(fields: Array): List { + val names = mutableListOf() + fields.forEach { field -> + names.add(field.name) + if (!field.type.isPrimitive + && !field.type.isArray + && !this._systemClass.contains(field.type.simpleName)) + names.addAll(this.traversalFields(field.type.declaredFields).map { "${field.name}.$it" }) + } + return names + } + + protected open fun where(query: Query, params: Map?): Query { + val criteria = Criteria() + if (params != null) { + for (param in params) { + val value = this.convertFieldValueType(param.key, param.value) + criteria.and(param.key).isEqualTo(value) + } + } + return query.addCriteria(criteria) + } + + protected fun convertFieldValueType(key: String, value: Any): Any? { + val getter = this.viewClass.getMethod("get${key.substring(0, 1).toUpperCase()}${key.substring(1)}") + return this.convertClass(getter.returnType, value.toString()) + } + + protected open fun select(query: Query, fields: Array): Query { + fields.forEach { + query.fields().include(it) + } + return query + } + + protected open fun order(orders: MutableMap?): Sort { + val orderList = mutableListOf() + orders?.forEach() { + orderList.add(Sort.Order(Sort.Direction.valueOf(it.value.name), it.key)) + } + return if (orderList.size == 0) + Sort.by("_id") + else + Sort.by(orderList) + } + + private fun convertClass(type: Class<*>, value: String): Any? { + + if (!type.isPrimitive) { // 判断基本类型 + if (type == String::class.java) { // 如果是string则直接返回 + return value + } + // 如果不为null 则通过反射实例一个对象返回 + return if ("" == value) null else type.getConstructor(String::class.java).newInstance(value) + } + + // 下面处理基本类型,返回包装类 + return when (type.name) { + "int" -> Integer.parseInt(value) + "byte" -> java.lang.Byte.parseByte(value) + "boolean" -> java.lang.Boolean.parseBoolean(value) + "double" -> java.lang.Double.parseDouble(value) + "float" -> java.lang.Float.parseFloat(value) + "long" -> java.lang.Long.parseLong(value) + "short" -> java.lang.Short.parseShort(value) + else -> value + } + } +} diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/repository/MongoRepository.kt b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/repository/MongoRepository.kt new file mode 100644 index 0000000..9708666 --- /dev/null +++ b/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/repository/MongoRepository.kt @@ -0,0 +1,35 @@ +package com.synebula.gaea.repository + +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.repository.ITypedRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.data.mongodb.core.query.Query +import org.springframework.data.mongodb.core.query.isEqualTo +import org.springframework.stereotype.Repository + +@Repository +abstract class MongoRepository> : ITypedRepository { + + @Autowired + private lateinit var repo: MongoTemplate + + override fun remove(id: String, clazz: Class) { + this.repo.remove(queryId(id), clazz) + } + + override fun get(id: String, clazz: Class): TAggregateRoot { + return this.repo.findOne(queryId(id), clazz) as TAggregateRoot + } + + override fun update(obj: TAggregateRoot) { + this.repo.save(obj) + } + + override fun add(obj: TAggregateRoot) { + this.repo.save(obj) + } + + protected fun queryId(id: String): Query = Query(Criteria("_id").isEqualTo(id)) +} \ No newline at end of file diff --git a/src/gaea/build.gradle b/src/gaea/build.gradle index ed89581..ea73262 100644 --- a/src/gaea/build.gradle +++ b/src/gaea/build.gradle @@ -2,9 +2,9 @@ publishing { publications { mavenJava(MavenPublication) { group 'com.synebula' - artifactId 'gaea.data' - version project.version + artifactId 'gaea' + version "$version" from components.java } } -} +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt index 95f9eec..d134eda 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Message.kt @@ -1,15 +1,47 @@ package com.synebula.gaea.data.message -import java.util.Date +import java.util.* -open class Message { +/** + * + * 用来统一Http返回消息类型,通常使用json格式传递 + * + * @param status http编码。200成功,400错误,500异常 + * @tparam T 消息数据类型 + */ +open class Message(var status: Int = Status.Success) { /** * 传递的业务数据 */ var data: T? = null + /** + * 附带提示消息 + */ + var message = "" + /** * 消息时间戳 */ val timestamp: Long = Date().time + + constructor(data: T) : this(Status.Success) { + this.data = data + } + + constructor(status: Int, message: String) : this(status) { + this.message = message + } + + constructor(status: Int, data: T, message: String) : this(status) { + this.data = data + this.message = message + } + + open fun from(other: Message) { + this.status = other.status + this.data = other.data + this.message = other.message + } } + diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt new file mode 100644 index 0000000..c61837d --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/Status.kt @@ -0,0 +1,18 @@ +package com.synebula.gaea.data.message + +object Status { + /** + * 成功 + */ + val Success = 200 + + /** + * 失败 + */ + val Failure = 400 + + /** + * 错误 + */ + val Error = 500 +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpMessage.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpMessage.kt deleted file mode 100644 index 7e11771..0000000 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpMessage.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.synebula.gaea.data.message.http - -import com.synebula.gaea.data.message.Message - -/** - * - * 用来统一Http返回消息类型,通常使用json格式传递 - * - * @param status http编码。200成功,400错误,500异常 - * @tparam T 消息数据类型 - */ -class HttpMessage(var status: Int = HttpStatus.Success.code) : Message() { - /** - * 附带提示消息 - */ - var message = "" - - constructor(data: T) : this(HttpStatus.Success.code) { - this.data = data - } - - constructor(status: Int, message: String) : this(status) { - this.message = message - } - - constructor(status: Int, data: T, message: String) : this(status) { - this.data = data - this.message = message - } - - fun from(other: HttpMessage) { - this.status = other.status - this.data = other.data - this.message = message - } -} - diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpStatus.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpStatus.kt deleted file mode 100644 index 113e969..0000000 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/data/message/http/HttpStatus.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.synebula.gaea.data.message.http - -/** - * 状态类型。 - * - * @author alex - * @version 0.0.1 - * @since 2016年9月6日 下午3:27:55 - */ -enum class HttpStatus(val code: Int) { - /** - * 成功 - */ - Success(200), - - /** - * 失败 - */ - Failure(400), - - /** - * 错误 - */ - Error(500); - - companion object { - fun valueOf(code: Int): HttpStatus { - return when (code) { - 200 -> HttpStatus.Success - 400 -> HttpStatus.Failure - else -> HttpStatus.Error - } - } - } - -} diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/AggregateRoot.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/AggregateRoot.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/AggregateRoot.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/AggregateRoot.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/Entity.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/Entity.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/Entity.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/Entity.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IAggregateRoot.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IAggregateRoot.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IAggregateRoot.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IAggregateRoot.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IEntity.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IEntity.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IEntity.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IEntity.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IValue.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IValue.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/IValue.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/IValue.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexAggregateRoot.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexAggregateRoot.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexAggregateRoot.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexAggregateRoot.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexEntity.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexEntity.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexEntity.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/ComplexEntity.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexAggregateRoot.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexAggregateRoot.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexAggregateRoot.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexAggregateRoot.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexEntity.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexEntity.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexEntity.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/model/complex/IComplexEntity.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/IComplexRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IComplexRepository.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/IComplexRepository.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IComplexRepository.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt similarity index 84% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt index 946bc80..8e208ab 100644 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ITypedRepository.kt @@ -9,7 +9,7 @@ interface ITypedRepository, TKey> { * @param obj 需要插入的对象。 * @return 返回原对象,如果对象ID为自增,则补充自增ID。 */ - fun add(obj: TAggregateRoot): Unit + fun add(obj: TAggregateRoot) /** * 更新对象。 @@ -17,7 +17,7 @@ interface ITypedRepository, TKey> { * @param obj 需要更新的对象。 * @return */ - fun update(obj: TAggregateRoot): Unit + fun update(obj: TAggregateRoot) /** * 通过id删除该条数据 @@ -25,7 +25,7 @@ interface ITypedRepository, TKey> { * @param id id * @param clazz 操作数据的类型 */ - fun remove(id: TKey, clazz: Class): Unit + fun remove(id: TKey, clazz: Class) /** * 根据ID获取对象。 diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/context/IContext.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/context/IContext.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/context/IContext.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/context/IContext.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/context/IUnitOfWork.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/context/IUnitOfWork.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/context/IUnitOfWork.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/context/IUnitOfWork.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndNotSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndNotSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndNotSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndNotSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AndSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AnySpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AnySpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AnySpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/AnySpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/CompositeSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/CompositeSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/CompositeSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/CompositeSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ICompositeSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ICompositeSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ICompositeSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ICompositeSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ISpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ISpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ISpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/ISpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NoneSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NoneSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NoneSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NoneSpecification.kt diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt new file mode 100644 index 0000000..f9cc24e --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/NotSpecification.kt @@ -0,0 +1,19 @@ +package com.synebula.gaea.domain.repository.specifications + +/** + * 逆反规约。 + * + * @author alex + * + * @param 规约对象的类型。 + * + * @param spec 需要逆反的规约对象。 + * + */ +class NotSpecification(private val spec: ISpecification) : Specification() { + + override fun isSatisfiedBy(obj: T): Boolean { + return !spec.isSatisfiedBy(obj) + } + +} diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrNotSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrNotSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrNotSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrNotSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrSpecification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrSpecification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrSpecification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/OrSpecification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/Specification.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/Specification.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/Specification.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/specifications/Specification.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Command.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt similarity index 89% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt index 630bc17..ff41b82 100644 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ComplexService.kt @@ -1,7 +1,7 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.IObjectConverter -import com.synebula.gaea.data.message.http.HttpMessage +import com.synebula.gaea.data.message.Message import com.synebula.gaea.domain.model.complex.IComplexAggregateRoot import com.synebula.gaea.domain.repository.IComplexRepository import com.synebula.gaea.log.ILogger @@ -18,8 +18,8 @@ open class ComplexService, protected var converter: IObjectConverter, protected var aggregateRootClass: Class) : IComplexService { - override fun add(command: ICommand): HttpMessage> { - val msg = HttpMessage>() + override fun add(command: ICommand): Message> { + val msg = Message>() val root = this.convert(command) repository.add(root) msg.data = Pair(root.id, root.secondary) diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/ICommand.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ICommand.kt similarity index 100% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/ICommand.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ICommand.kt diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt similarity index 70% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt index a0c4005..146ed06 100644 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IComplexService.kt @@ -1,6 +1,6 @@ package com.synebula.gaea.domain.service -import com.synebula.gaea.data.message.http.HttpMessage +import com.synebula.gaea.data.message.Message /** * class IFlatService @@ -11,7 +11,7 @@ import com.synebula.gaea.data.message.http.HttpMessage */ interface IComplexService { - fun add(command: ICommand): HttpMessage> + fun add(command: ICommand): Message> fun update(key: TKey, secondary: TSecond, command: ICommand) diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt similarity index 80% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt index 6a12a2c..6e283ab 100644 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt @@ -1,6 +1,6 @@ package com.synebula.gaea.domain.service -import com.synebula.gaea.data.message.http.HttpMessage +import com.synebula.gaea.data.message.Message import com.synebula.gaea.log.ILogger @@ -16,7 +16,7 @@ interface IService { */ var logger: ILogger - fun add(command: ICommand): HttpMessage + fun add(command: ICommand): Message fun update(key: TKey, command: ICommand) diff --git a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt similarity index 89% rename from src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt index 7b2a205..27482c5 100644 --- a/src/gaea.domain/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt @@ -1,7 +1,7 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.IObjectConverter -import com.synebula.gaea.data.message.http.HttpMessage +import com.synebula.gaea.data.message.Message import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.repository.IRepository import com.synebula.gaea.log.ILogger @@ -20,8 +20,8 @@ open class Service, TKey> protected var converter: IObjectConverter, protected var aggregateRootClass: Class) : IService { - override fun add(command: ICommand): HttpMessage { - val msg = HttpMessage() + override fun add(command: ICommand): Message { + val msg = Message() val root = this.convert(command) repository.add(root) msg.data = root.id diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassLoaderContext.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassLoaderContext.kt new file mode 100644 index 0000000..2beaead --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassLoaderContext.kt @@ -0,0 +1,23 @@ +package com.synebula.gaea.io.scan + +/** + * + * @author alex + * @version 0.0.1 + * @since 2016年9月20日 上午10:50:06 + */ +object ClassLoaderContext { + /** + * 获得class loader

+ * 若当前线程class loader不存在,取当前类的class loader + * + * @return 类加载器 + */ + fun get(): ClassLoader { + var classLoader: ClassLoader? = Thread.currentThread().contextClassLoader + if (classLoader == null) { + classLoader = ClassLoaderContext::class.java.classLoader + } + return classLoader!! + } +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt new file mode 100644 index 0000000..a62caba --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassPath.kt @@ -0,0 +1,49 @@ +package com.synebula.gaea.io.scan + +import java.io.IOException +import java.net.URL +import java.util.Enumeration +import java.util.HashSet + +/** + * + * @author alex + * @version 0.0.1 + * @since 2016年9月20日 下午2:59:47 + */ +object ClassPath { + + /** + * 获得Java ClassPath路径 + * @return 获得Java ClassPath路径,不包括 jre + */ + fun get(): Array { + val paths = System.getProperty("java.class.path") + val separator = System.getProperty("path.separator") + return paths.split(separator.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + } + + /** + * 获得ClassPath + * + * @param packageName 包名称 + * @return ClassPath路径字符串集合 + */ + fun get(packageName: String): Array { + val paths = HashSet() + var path = packageName.replace(".", "/") + // 判断路径最后一个字符是不是"/",如果不是加上 + path = if (path.lastIndexOf("/") != path.length - 1) "$path/" else path + + var resources: Enumeration? = null + try { + resources = ClassLoaderContext.get().getResources(path) + } catch (e: IOException) { + } + + while (resources!!.hasMoreElements()) { + paths.add(resources.nextElement().path) + } + return paths.toTypedArray() + } +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt new file mode 100644 index 0000000..fb1b904 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/ClassScanner.kt @@ -0,0 +1,202 @@ +package com.synebula.gaea.io.scan + +import java.io.File +import java.io.FileFilter +import java.io.UnsupportedEncodingException +import java.net.URLDecoder +import java.nio.charset.Charset +import java.util.Collections +import java.util.HashSet +import java.util.LinkedList +import java.util.jar.JarFile + +/** + * 包扫描组件 + * @author alex + * @version 0.0.1 + * @since 2016年9月20日 下午2:56:50 + * + * @param packageName 扫描的包名 + */ +class ClassScanner(private var packageName: String) { + /** + * 类过滤器列表 + */ + private var classFilters: Array? = null + + /** + * 扫描的类 + */ + private val classes: MutableSet> = HashSet() + + /** + * 文件过滤器 + */ + private val fileFilter = FileFilter { file -> file.isDirectory || file.name.endsWith(".class") || file.name.endsWith(".jar") } + + + /** + * 构造方法。 + * + * @param packageName 需要扫描的包名。 + * @param classFilter + */ + constructor(packageName: String, vararg classFilter: IClassFilter) : this(packageName) { + this.classFilters = classFilter + } + + /** + * 开始扫描。 + * + * @return + */ + fun scan(): Collection> { + // 如果类集合不为空,先清空。 + if (classes.isNotEmpty()) + classes.clear() + + var paths = ClassPath.get(packageName)// 先扫描当前类路径下文件 + this.scanPath(paths) + if (classes.isEmpty()) {// 若当前类路径下文件没有,扫描java路径 + paths = ClassPath.get() + this.scanPath(paths) + } + return classes + } + + /* + * Private + * + */ + + /** + * 填充满足条件的class 填充到 classes

+ * 同时会判断给定的路径是否为Jar包内的路径,如果是,则扫描此Jar包 + * + * @param paths Class文件路径或者所在目录Jar包路径 + */ + private fun scanPath(paths: Array) { + for (path in paths) { + try { + // 路径编码,防止由于路径中空格和中文导致的Jar找不到 + val realPath = URLDecoder.decode(path, Charset.defaultCharset().name()) + val files = scanDirectory(realPath) + for (file in files) { + val fileName = file.toString() + if (fileName.contains(".jar") && !fileName.endsWith(".class")) + scanJar(file) + else if (fileName.endsWith(".class")) + scanClass(realPath, file) + } + } catch (e: UnsupportedEncodingException) { + } + } + } + + /** + * 扫描文件,过滤添加类文件。 + * + * @param path 扫描的磁盘路径 + */ + private fun scanDirectory(path: String): Collection { + var realPath = path + val files = LinkedList() + val index = realPath.lastIndexOf(".jar") + if (index != -1) {// 首先判path是不是jar包下,如果是说明当前path是文件 + // jar文件 + realPath = realPath.substring(0, index + 4)// 截取jar路径 [xxx/xxx.jar] + if (realPath.startsWith("file:")) + realPath = realPath.substring(5) // 去掉文件前缀[file:] + files.add(File(realPath)) + } else {// 否则扫描文件夹下文件 + val directory = LinkedList() + directory.add(File(realPath)) + var list: Array? + var file: File + while (directory.size != 0) { + file = directory.poll() + list = file.listFiles(fileFilter) + if (list!!.isNotEmpty()) { + for (item in list) { + if (item.isDirectory) + directory.add(item) + else + files.add(item) + } + } + } + } + return files + } + + /** + * 扫描jar文件,过滤添加类文件。 + * + * @param file 扫描的jar文件 + */ + private fun scanJar(file: File) { + try { + val jar = JarFile(file) + val entries = jar.entries() + val list = Collections.list(entries) + for (entry in list) { + if (entry.name.endsWith(".class")) { + val className = entry.name.replace("/", ".").replace(".class", "") + filterClass(className) + } + } + jar.close() + } catch (ex: Throwable) { + } + + } + + /** + * 扫描.class类文件,过滤添加类文件。 + * + * @param path 路径 + * @param file 文件 + */ + private fun scanClass(path: String, file: File) { + var realPath = path + if (!realPath.endsWith(File.separator)) { + realPath += File.separator + } + var absolutePath = file.absolutePath + if (packageName.isEmpty()) + absolutePath = absolutePath.substring(realPath.length) + + val filePathWithDot = absolutePath.replace(File.separator, ".") + val subIndex = filePathWithDot.indexOf(packageName) + if (subIndex != -1) { + val endIndex = filePathWithDot.lastIndexOf(".class") + val className = filePathWithDot.substring(subIndex, endIndex) + filterClass(className) + } + } + + /** + * 过滤符合要求的类,添加到结果列表中。 + * + * @param className 类名 + */ + private fun filterClass(className: String) { + if (className.startsWith(packageName)) { + try { + val clazz = Class.forName(className, false, ClassLoaderContext.get()) + if (classFilters == null) + classes.add(clazz) + else { + for (iClassFilter in classFilters!!) { + if (iClassFilter.accept(clazz)) + classes.add(clazz) + } + } + } catch (ex: Throwable) { + + } + + } + } + +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/IClassFilter.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/IClassFilter.kt new file mode 100644 index 0000000..b98f585 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/io/scan/IClassFilter.kt @@ -0,0 +1,11 @@ +package com.synebula.gaea.io.scan + +/** + * 类过滤器,用于过滤不需要加载的类

+ * @author alex + * @version 0.0.1 + * @since 2016年9月18日 下午4:41:29 + */ +interface IClassFilter { + fun accept(clazz: Class<*>): Boolean +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/IComplexQuery.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IComplexQuery.kt new file mode 100644 index 0000000..49ff1ad --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IComplexQuery.kt @@ -0,0 +1,42 @@ +package com.synebula.gaea.query + +/** + * 查询基接口。 + * + * @author wxf + */ +interface IComplexQuery { + + + /** + * 根据Key获取对象。 + * + * @param key 对象Key。 + * @return + */ + fun get(key: TKey, secondary: TSecond): TView + + /** + * 根据实体类条件查询所有符合条件记录 + * + * @param parameters 查询条件。 + * @return list + */ + fun list(parameters: Map): List + + /** + * 根据条件查询符合条件记录的数量 + * + * @param parameters 查询条件。 + * @return int + */ + fun count(parameters: Map): Int + + /** + * 根据实体类条件查询所有符合条件记录(分页查询) + * + * @param param 分页条件 + * @return + */ + fun paging(param: PagingParam): PagingData +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt new file mode 100644 index 0000000..3ae09bc --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt @@ -0,0 +1,42 @@ +package com.synebula.gaea.query + +/** + * 查询基接口。 + * + * @author alex + */ +interface IQuery { + + + /** + * 根据Key获取对象。 + * + * @param key 对象Key。 + * @return + */ + fun get(key: TKey): TView? + + /** + * 根据实体类条件查询所有符合条件记录 + * + * @param params 查询条件。 + * @return list + */ + fun list(params: Map?): List + + /** + * 根据条件查询符合条件记录的数量 + * + * @param params 查询条件。 + * @return int + */ + fun count(params: Map?): Int + + /** + * 根据实体类条件查询所有符合条件记录(分页查询) + * + * @param params 分页条件 + * @return 分页数据 + */ + fun paging(params: PagingParam): PagingData +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/OrderType.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/OrderType.kt new file mode 100644 index 0000000..1865296 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/OrderType.kt @@ -0,0 +1,20 @@ +package com.synebula.gaea.query + +/** + * class OrderType + * + * @author alex + * @version 0.1 + * @since 2018 18-2-6 + */ +enum class OrderType { + /** + * 升序排列 + */ + ASC, + + /** + * 降序排序 + */ + DESC +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingData.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingData.kt new file mode 100644 index 0000000..8997da9 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingData.kt @@ -0,0 +1,67 @@ +package com.synebula.gaea.query + +/** + * 分页数据。 + * 真实数据行无后台遍历需求,直接使用object类型表示即可. + * + * @author alex + */ +class PagingData { + /** + * 页码,从1开始。 + */ + var page: Int = 0 + + /** + * 每页数据量。 + */ + + var size: Int = 0 + + /** + * 总数据量。 + */ + + var total: Int = 0 + + /** + * 数据索引,从0开始。表示数据在总量的第几条。(index = (page - 1) * size ) + */ + var index: Int + get() = (page - 1) * size + + /** + * 结果数据。 + */ + var data = listOf() + + + /** + * 数据构造。 + * + * @param page 页码,从1开始。 + * @param size 每页数据量。 + */ + constructor(page: Int, size: Int) : super() { + this.page = page + this.size = size + this.index = (page - 1) * size + 1 + } + + /** + * 数据构造。 + * + * @param page 页码,从1开始。 + * @param size 每页数据量。 + * @param total 总数据量。 + * @param data 结果数据。 + */ + + constructor(page: Int, size: Int, total: Int, data: List) : super() { + this.page = page + this.size = size + this.total = total + this.index = (page - 1) * size + 1 + this.data = data + } +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingParam.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingParam.kt new file mode 100644 index 0000000..de61140 --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/PagingParam.kt @@ -0,0 +1,44 @@ +package com.synebula.gaea.query + +/** + * class PagingParam + * + * @author alex + * @version 0.1 + * @since 2018 18-2-5 + */ +data class PagingParam(var page: Int = 1, var size: Int = 10) { + + /** + * 数据索引,从0开始。表示数据在总量的第几条。(index = (page - 1) * size) + */ + var index: Long = 0 + get() = (page.toLong() - 1) * size.toLong() + private set + + /** + * 排序条件。 + */ + var orderBy: MutableMap = hashMapOf() + + /** + * 查询条件。 + */ + var parameters: MutableMap = hashMapOf() + + /** + * 添加查询条件 + */ + fun addParameter(field: String, value: Any): PagingParam { + parameters[field] = value + return this + } + + /** + * 添加排序条件 + */ + fun addOrderBy(field: String, type: OrderType = OrderType.ASC): PagingParam { + orderBy[field] = type + return this + } +}