From fddf7bb60ea2cd0b221dff4e7ae3007ed87df4f4 Mon Sep 17 00:00:00 2001 From: pnoker Date: Mon, 27 Apr 2026 19:46:15 +0800 Subject: [PATCH] feat(facade): introduce facade layer for cross-service calls Adds three new modules that let business code call center services through protocol-neutral interfaces instead of @GrpcClient stubs: - dc3-common-facade-api: Device/Driver/Point + Tenant/User/UserLogin/Token facade interfaces plus facade-owned BO/Query/Page types - dc3-common-facade-local: in-process implementations backed by the auth/manager services; zero serialization cost in single deployments - dc3-common-facade-grpc: gRPC implementations holding BlockingStubs; default mode for distributed deployments Implementation selection is driven by dc3.facade.mode={local|grpc} via @ConditionalOnProperty, with grpc as the matchIfMissing default. Wire-up for dc3-center-single (dc3.facade.mode=local + facade-local dependency) is included so the single-deployment mode is runnable out of the box. --- dc3-center/dc3-center-single/pom.xml | 4 + .../src/main/resources/application.yml | 4 + dc3-common/dc3-common-facade-api/pom.xml | 54 +++++++ .../common/facade/api/DeviceFacade.java | 71 ++++++++++ .../common/facade/api/DriverFacade.java | 52 +++++++ .../pnoker/common/facade/api/PointFacade.java | 42 ++++++ .../common/facade/api/TenantFacade.java | 34 +++++ .../pnoker/common/facade/api/TokenFacade.java | 42 ++++++ .../pnoker/common/facade/api/UserFacade.java | 34 +++++ .../common/facade/api/UserLoginFacade.java | 34 +++++ .../facade/entity/bo/FacadeDeviceBO.java | 62 ++++++++ .../facade/entity/bo/FacadeDriverBO.java | 58 ++++++++ .../facade/entity/bo/FacadePointBO.java | 69 +++++++++ .../facade/entity/bo/FacadeTenantBO.java | 43 ++++++ .../common/facade/entity/bo/FacadeUserBO.java | 49 +++++++ .../facade/entity/bo/FacadeUserLoginBO.java | 45 ++++++ .../facade/entity/common/FacadePage.java | 59 ++++++++ .../entity/query/FacadeDeviceQuery.java | 61 ++++++++ .../entity/query/FacadeDriverQuery.java | 62 ++++++++ .../facade/entity/query/FacadePointQuery.java | 68 +++++++++ dc3-common/dc3-common-facade-grpc/pom.xml | 78 +++++++++++ .../common/facade/grpc/DeviceGrpcFacade.java | 126 +++++++++++++++++ .../common/facade/grpc/DriverGrpcFacade.java | 106 ++++++++++++++ .../common/facade/grpc/PointGrpcFacade.java | 95 +++++++++++++ .../common/facade/grpc/TenantGrpcFacade.java | 69 +++++++++ .../common/facade/grpc/TokenGrpcFacade.java | 53 +++++++ .../common/facade/grpc/UserGrpcFacade.java | 69 +++++++++ .../facade/grpc/UserLoginGrpcFacade.java | 69 +++++++++ .../grpc/builder/FacadeGrpcDeviceBuilder.java | 105 ++++++++++++++ .../grpc/builder/FacadeGrpcDriverBuilder.java | 108 ++++++++++++++ .../grpc/builder/FacadeGrpcPointBuilder.java | 132 ++++++++++++++++++ .../grpc/builder/FacadeGrpcTenantBuilder.java | 53 +++++++ .../grpc/builder/FacadeGrpcUserBuilder.java | 55 ++++++++ .../builder/FacadeGrpcUserLoginBuilder.java | 55 ++++++++ .../config/GrpcFacadeAutoConfiguration.java | 37 +++++ ...ot.autoconfigure.AutoConfiguration.imports | 18 +++ dc3-common/dc3-common-facade-local/pom.xml | 58 ++++++++ .../facade/local/DeviceLocalFacade.java | 93 ++++++++++++ .../facade/local/DriverLocalFacade.java | 77 ++++++++++ .../common/facade/local/PointLocalFacade.java | 71 ++++++++++ .../facade/local/TenantLocalFacade.java | 52 +++++++ .../common/facade/local/TokenLocalFacade.java | 48 +++++++ .../common/facade/local/UserLocalFacade.java | 52 +++++++ .../facade/local/UserLoginLocalFacade.java | 53 +++++++ .../local/builder/FacadeDeviceBuilder.java | 40 ++++++ .../local/builder/FacadeDriverBuilder.java | 39 ++++++ .../local/builder/FacadePointBuilder.java | 39 ++++++ .../local/builder/FacadeTenantBuilder.java | 36 +++++ .../local/builder/FacadeUserBuilder.java | 62 ++++++++ .../local/builder/FacadeUserLoginBuilder.java | 35 +++++ .../config/LocalFacadeAutoConfiguration.java | 36 +++++ ...ot.autoconfigure.AutoConfiguration.imports | 18 +++ dc3-common/pom.xml | 18 +++ pom.xml | 15 ++ 54 files changed, 3017 insertions(+) create mode 100644 dc3-common/dc3-common-facade-api/pom.xml create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DeviceFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DriverFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/PointFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TenantFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TokenFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserLoginFacade.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDeviceBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDriverBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadePointBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeTenantBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserLoginBO.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/common/FacadePage.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDeviceQuery.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDriverQuery.java create mode 100644 dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadePointQuery.java create mode 100644 dc3-common/dc3-common-facade-grpc/pom.xml create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DeviceGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DriverGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/PointGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TenantGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TokenGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserLoginGrpcFacade.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDeviceBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDriverBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcPointBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcTenantBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserLoginBuilder.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/config/GrpcFacadeAutoConfiguration.java create mode 100644 dc3-common/dc3-common-facade-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 dc3-common/dc3-common-facade-local/pom.xml create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DeviceLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DriverLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/PointLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TenantLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TokenLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLoginLocalFacade.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDeviceBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDriverBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadePointBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeTenantBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserLoginBuilder.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/config/LocalFacadeAutoConfiguration.java create mode 100644 dc3-common/dc3-common-facade-local/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/dc3-center/dc3-center-single/pom.xml b/dc3-center/dc3-center-single/pom.xml index 6d0da49a8..b9d8d72d6 100644 --- a/dc3-center/dc3-center-single/pom.xml +++ b/dc3-center/dc3-center-single/pom.xml @@ -43,6 +43,10 @@ io.github.pnoker dc3-common-data + + io.github.pnoker + dc3-common-facade-local + io.github.pnoker dc3-common-manager diff --git a/dc3-center/dc3-center-single/src/main/resources/application.yml b/dc3-center/dc3-center-single/src/main/resources/application.yml index 26f82905a..232c4f102 100644 --- a/dc3-center/dc3-center-single/src/main/resources/application.yml +++ b/dc3-center/dc3-center-single/src/main/resources/application.yml @@ -40,6 +40,10 @@ data: speed: ${POINT_BATCH_SPEED:100} interval: ${POINT_BATCH_INTERVAL:5} +dc3: + facade: + mode: ${DC3_FACADE_MODE:local} + logging: file: name: dc3/logs/center/single/${spring.application.name}.log \ No newline at end of file diff --git a/dc3-common/dc3-common-facade-api/pom.xml b/dc3-common/dc3-common-facade-api/pom.xml new file mode 100644 index 000000000..98cc84edb --- /dev/null +++ b/dc3-common/dc3-common-facade-api/pom.xml @@ -0,0 +1,54 @@ + + + + 4.0.0 + + + io.github.pnoker + dc3-common + 2026.4.19 + + + ${project.artifactId} + dc3-common-facade-api + 2026.4.19 + jar + + 2016 + https://github.com/pnoker/iot-dc3 + + The Facade API of the IoT DC3 platform. Protocol-neutral interfaces and BO/Query/Page types + used to decouple callers from the underlying transport (local or gRPC). + + + + + + + io.github.pnoker + dc3-common-constant + + + io.github.pnoker + dc3-common-model + + + + + diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DeviceFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DeviceFacade.java new file mode 100644 index 000000000..2d129bc40 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DeviceFacade.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDeviceQuery; + +import java.util.List; + +/** + * Protocol-neutral device facade. + *

+ * Mirrors the four RPCs on {@code api.center.manager.DeviceApi} but returns plain + * BO/Page types so callers never have to touch gRPC or protobuf classes. + * Two implementations back this interface: + *

    + *
  • {@code DeviceLocalFacade} — in-process call into {@code DeviceService}, + * selected when {@code dc3.facade.mode=local} (single deployment).
  • + *
  • {@code DeviceGrpcFacade} — gRPC call against Manager Center, + * selected when {@code dc3.facade.mode=grpc} (distributed deployment, default).
  • + *
+ * + * @author pnoker + * @since 2026.4.19 + */ +public interface DeviceFacade { + + /** + * Query a single device by id. + * + * @return the device, or {@code null} when the device does not exist. + */ + FacadeDeviceBO selectById(Long id); + + /** + * Paginated query. + * + * @return a page of devices (never {@code null}; empty page when nothing matches). + */ + FacadePage selectByPage(FacadeDeviceQuery query); + + /** + * List devices attached to a given profile. + * + * @return an immutable list (never {@code null}; empty when nothing matches). + */ + List selectByProfileId(Long profileId); + + /** + * List devices attached to a given driver. + * + * @return an immutable list (never {@code null}; empty when nothing matches). + */ + List selectByDriverId(Long driverId); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DriverFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DriverFacade.java new file mode 100644 index 000000000..9d318054c --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/DriverFacade.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDriverQuery; + +/** + * Protocol-neutral driver facade. + *

+ * Mirrors the three RPCs on {@code api.center.manager.DriverApi}. + * Implementation selection follows the same {@code dc3.facade.mode} switch + * used by {@link DeviceFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface DriverFacade { + + /** + * @return the driver, or {@code null} when it does not exist. + */ + FacadeDriverBO selectById(Long id); + + /** + * @return a page of drivers (never {@code null}; empty page when nothing matches). + */ + FacadePage selectByPage(FacadeDriverQuery query); + + /** + * Resolve the driver that owns a given device. + * + * @return the driver, or {@code null} when the device has no bound driver. + */ + FacadeDriverBO selectByDeviceId(Long deviceId); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/PointFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/PointFacade.java new file mode 100644 index 000000000..d644d1a2b --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/PointFacade.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadePointBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadePointQuery; + +/** + * Protocol-neutral point facade. Mirrors the two RPCs on + * {@code api.center.manager.PointApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface PointFacade { + + /** + * @return the point, or {@code null} when it does not exist. + */ + FacadePointBO selectById(Long id); + + /** + * @return a page of points (never {@code null}; empty page when nothing matches). + */ + FacadePage selectByPage(FacadePointQuery query); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TenantFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TenantFacade.java new file mode 100644 index 000000000..05494396b --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TenantFacade.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadeTenantBO; + +/** + * Protocol-neutral tenant facade. Mirrors {@code api.center.auth.TenantApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface TenantFacade { + + /** + * @return the tenant, or {@code null} when no tenant carries the given code. + */ + FacadeTenantBO selectByCode(String code); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TokenFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TokenFacade.java new file mode 100644 index 000000000..24a854b1e --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/TokenFacade.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +/** + * Protocol-neutral token facade. Mirrors {@code api.center.auth.TokenApi}. + *

+ * Returns a plain boolean rather than a {@code TokenBO} because callers only + * care whether the token is valid — the existing RPC only returns an expiry + * string that nobody reads from the gateway. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface TokenFacade { + + /** + * Validate a token triple against the backing auth service. + * + * @param tenant tenant code + * @param name login name + * @param salt salt the client holds + * @param token token the client holds + * @return {@code true} when the triple is valid and unexpired + */ + boolean checkValid(String tenant, String name, String salt, String token); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserFacade.java new file mode 100644 index 000000000..6a87c2636 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserFacade.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadeUserBO; + +/** + * Protocol-neutral user facade. Mirrors {@code api.center.auth.UserApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface UserFacade { + + /** + * @return the user, or {@code null} when the id does not match any user. + */ + FacadeUserBO selectById(Long id); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserLoginFacade.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserLoginFacade.java new file mode 100644 index 000000000..8e42aa01f --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/api/UserLoginFacade.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.api; + +import io.github.pnoker.common.facade.entity.bo.FacadeUserLoginBO; + +/** + * Protocol-neutral user-login facade. Mirrors {@code api.center.auth.UserLoginApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +public interface UserLoginFacade { + + /** + * @return the user-login record, or {@code null} when the login name does not exist. + */ + FacadeUserLoginBO selectByName(String name); +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDeviceBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDeviceBO.java new file mode 100644 index 000000000..d6a6bbf6b --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDeviceBO.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import io.github.pnoker.common.entity.ext.DeviceExt; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +import java.util.List; + +/** + * Facade-level device BO. + *

+ * Field set matches {@code api.center.manager.DeviceApi} wire shape. Intentionally + * excludes driver-side attachments (pointIds, attributeConfig maps) — those remain + * in {@code dc3-common-driver}'s DeviceBO and are not part of the center-to-center + * contract. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadeDeviceBO extends BaseBO { + + private String deviceName; + + private String deviceCode; + + private Long driverId; + + private DeviceExt deviceExt; + + private EnableFlagEnum enableFlag; + + private Long tenantId; + + private String signature; + + private Integer version; + + private List profileIds; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDriverBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDriverBO.java new file mode 100644 index 000000000..c198e0dfd --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeDriverBO.java @@ -0,0 +1,58 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import io.github.pnoker.common.entity.ext.DriverExt; +import io.github.pnoker.common.enums.DriverTypeFlagEnum; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +/** + * Facade-level driver BO. Field set matches {@code api.center.manager.DriverApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadeDriverBO extends BaseBO { + + private String driverName; + + private String driverCode; + + private String serviceName; + + private String serviceHost; + + private DriverTypeFlagEnum driverTypeFlag; + + private DriverExt driverExt; + + private EnableFlagEnum enableFlag; + + private Long tenantId; + + private String signature; + + private Integer version; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadePointBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadePointBO.java new file mode 100644 index 000000000..b718d4a97 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadePointBO.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import io.github.pnoker.common.entity.ext.PointExt; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.enums.PointTypeFlagEnum; +import io.github.pnoker.common.enums.RwFlagEnum; +import lombok.*; + +import java.math.BigDecimal; + +/** + * Facade-level point BO. Field set matches {@code api.center.manager.PointApi}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadePointBO extends BaseBO { + + private String pointName; + + private String pointCode; + + private PointTypeFlagEnum pointTypeFlag; + + private RwFlagEnum rwFlag; + + private BigDecimal baseValue; + + private BigDecimal multiple; + + private Byte valueDecimal; + + private String unit; + + private Long profileId; + + private PointExt pointExt; + + private EnableFlagEnum enableFlag; + + private Long tenantId; + + private String signature; + + private Integer version; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeTenantBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeTenantBO.java new file mode 100644 index 000000000..7937a4102 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeTenantBO.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +/** + * Facade-level tenant BO. Field set matches {@code api.center.auth.TenantApi} + * wire shape (no tenantExt — that is not exposed through gRPC). + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadeTenantBO extends BaseBO { + + private String tenantName; + + private String tenantCode; + + private EnableFlagEnum enableFlag; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserBO.java new file mode 100644 index 000000000..a5537552a --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserBO.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import lombok.*; + +/** + * Facade-level user BO. Field set matches {@code api.center.auth.UserApi} wire + * shape — {@code enableFlag} is intentionally absent because the + * {@code GrpcUserDTO} contract does not expose it. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadeUserBO extends BaseBO { + + private String nickName; + + private String userName; + + private String phone; + + private String email; + + private String socialExt; + + private String identityExt; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserLoginBO.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserLoginBO.java new file mode 100644 index 000000000..ed11f5133 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/bo/FacadeUserLoginBO.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.bo; + +import io.github.pnoker.common.entity.base.BaseBO; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +/** + * Facade-level user-login BO. Field set matches + * {@code api.center.auth.UserLoginApi} wire shape. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString(callSuper = true) +public class FacadeUserLoginBO extends BaseBO { + + private String loginName; + + private Long userId; + + private Long userPasswordId; + + private EnableFlagEnum enableFlag; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/common/FacadePage.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/common/FacadePage.java new file mode 100644 index 000000000..177833505 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/common/FacadePage.java @@ -0,0 +1,59 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.common; + +import lombok.*; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +/** + * Transport-neutral page envelope for facade return values. + *

+ * Intentionally does not extend MyBatis-Plus {@code Page} so that + * {@code dc3-common-facade-api} keeps zero persistence dependencies. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class FacadePage implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private long current; + + private long size; + + private long total; + + private long pages; + + private List records; + + public static FacadePage empty() { + return new FacadePage<>(1L, 0L, 0L, 0L, Collections.emptyList()); + } +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDeviceQuery.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDeviceQuery.java new file mode 100644 index 000000000..e835517f2 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDeviceQuery.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.query; + +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +import java.io.Serial; +import java.io.Serializable; + +/** + * Facade-level device query. + *

+ * Field set matches the filters supported by {@code DeviceApi.SelectByPage}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@Builder +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class FacadeDeviceQuery implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Pages page; + + private Long tenantId; + + private String deviceName; + + private String deviceCode; + + private Long driverId; + + private EnableFlagEnum enableFlag; + + private Integer version; + + private Long profileId; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDriverQuery.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDriverQuery.java new file mode 100644 index 000000000..4e0965c78 --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadeDriverQuery.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.query; + +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.enums.DriverTypeFlagEnum; +import io.github.pnoker.common.enums.EnableFlagEnum; +import lombok.*; + +import java.io.Serial; +import java.io.Serializable; + +/** + * Facade-level driver query. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@Builder +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class FacadeDriverQuery implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Pages page; + + private Long tenantId; + + private String driverName; + + private String driverCode; + + private String serviceName; + + private String serviceHost; + + private DriverTypeFlagEnum driverTypeFlag; + + private EnableFlagEnum enableFlag; + + private Integer version; +} diff --git a/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadePointQuery.java b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadePointQuery.java new file mode 100644 index 000000000..321009add --- /dev/null +++ b/dc3-common/dc3-common-facade-api/src/main/java/io/github/pnoker/common/facade/entity/query/FacadePointQuery.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.entity.query; + +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.enums.PointTypeFlagEnum; +import io.github.pnoker.common.enums.RwFlagEnum; +import lombok.*; + +import java.io.Serial; +import java.io.Serializable; + +/** + * Facade-level point query. + * + * @author pnoker + * @since 2026.4.19 + */ +@Getter +@Setter +@Builder +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class FacadePointQuery implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Pages page; + + private Long tenantId; + + private String pointName; + + private String pointCode; + + private PointTypeFlagEnum pointTypeFlag; + + private RwFlagEnum rwFlag; + + private Long profileId; + + private EnableFlagEnum enableFlag; + + private Integer version; + + /** + * Device ID — filter points bound to a specific device. + */ + private Long deviceId; +} diff --git a/dc3-common/dc3-common-facade-grpc/pom.xml b/dc3-common/dc3-common-facade-grpc/pom.xml new file mode 100644 index 000000000..36e706a9d --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/pom.xml @@ -0,0 +1,78 @@ + + + + 4.0.0 + + + io.github.pnoker + dc3-common + 2026.4.19 + + + ${project.artifactId} + dc3-common-facade-grpc + 2026.4.19 + jar + + 2016 + https://github.com/pnoker/iot-dc3 + + gRPC implementation of the Facade API, selected when dc3.facade.mode=grpc (default). + Holds BlockingStubs and translates between Facade BO/Query and protobuf DTOs. + + + + + + + net.devh + grpc-spring-boot-starter + + + + + io.github.pnoker + dc3-api-auth + + + io.github.pnoker + dc3-api-manager + + + + + io.github.pnoker + dc3-common-api + + + io.github.pnoker + dc3-common-exception + + + io.github.pnoker + dc3-common-facade-api + + + io.github.pnoker + dc3-common-public + + + + + diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DeviceGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DeviceGrpcFacade.java new file mode 100644 index 000000000..35b1aea6f --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DeviceGrpcFacade.java @@ -0,0 +1,126 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.manager.*; +import io.github.pnoker.api.common.GrpcDeviceDTO; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.ManagerConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.DeviceFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDeviceQuery; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcDeviceBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; + +/** + * gRPC implementation: forwards each call to Manager Center via + * {@link DeviceApiGrpc.DeviceApiBlockingStub}. + *

+ * Selected when {@code dc3.facade.mode=grpc} (or unset — grpc is the default + * in the auto-configuration declaration). + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class DeviceGrpcFacade implements DeviceFacade { + + @GrpcClient(ManagerConstant.SERVICE_NAME) + private DeviceApiGrpc.DeviceApiBlockingStub deviceApiBlockingStub; + + @Resource + private FacadeGrpcDeviceBuilder facadeGrpcDeviceBuilder; + + @Override + public FacadeDeviceBO selectById(Long id) { + GrpcDeviceQuery request = GrpcDeviceQuery.newBuilder().setDeviceId(id).build(); + GrpcRDeviceDTO response = deviceApiBlockingStub.selectByDeviceId(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectById"); + return null; + } + return facadeGrpcDeviceBuilder.toFacadeBO(response.getData()); + } + + @Override + public FacadePage selectByPage(FacadeDeviceQuery query) { + GrpcPageDeviceQuery request = facadeGrpcDeviceBuilder.toGrpcPageQuery(query); + GrpcRPageDeviceDTO response = deviceApiBlockingStub.selectByPage(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByPage"); + return FacadePage.empty(); + } + + GrpcPageDeviceDTO pageDTO = response.getData(); + List records = pageDTO.getDataList().stream() + .map(facadeGrpcDeviceBuilder::toFacadeBO) + .toList(); + + return new FacadePage<>( + pageDTO.getPage().getCurrent(), + pageDTO.getPage().getSize(), + pageDTO.getPage().getTotal(), + pageDTO.getPage().getPages(), + records); + } + + @Override + public List selectByProfileId(Long profileId) { + GrpcProfileQuery request = GrpcProfileQuery.newBuilder().setProfileId(profileId).build(); + GrpcRDeviceListDTO response = deviceApiBlockingStub.selectByProfileId(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByProfileId"); + return Collections.emptyList(); + } + return response.getDataList().stream().map(facadeGrpcDeviceBuilder::toFacadeBO).toList(); + } + + @Override + public List selectByDriverId(Long driverId) { + GrpcDriverQuery request = GrpcDriverQuery.newBuilder().setDriverId(driverId).build(); + GrpcRDeviceListDTO response = deviceApiBlockingStub.selectByDriverId(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByDriverId"); + return Collections.emptyList(); + } + return response.getDataList().stream().map(facadeGrpcDeviceBuilder::toFacadeBO).toList(); + } + + /** + * NO_RESOURCE is a normal "not found" signal — swallow and let the caller see null / empty. + * Any other non-OK code (server error, param error, etc.) escalates to an exception. + */ + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("DeviceGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("DeviceFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DriverGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DriverGrpcFacade.java new file mode 100644 index 000000000..82a67854f --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/DriverGrpcFacade.java @@ -0,0 +1,106 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.manager.*; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.ManagerConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.DriverFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDriverQuery; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcDriverBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * gRPC DriverFacade: forwards to Manager Center via + * {@link DriverApiGrpc.DriverApiBlockingStub}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class DriverGrpcFacade implements DriverFacade { + + @GrpcClient(ManagerConstant.SERVICE_NAME) + private DriverApiGrpc.DriverApiBlockingStub driverApiBlockingStub; + + @Resource + private FacadeGrpcDriverBuilder facadeGrpcDriverBuilder; + + @Override + public FacadeDriverBO selectById(Long id) { + GrpcDriverQuery request = GrpcDriverQuery.newBuilder().setDriverId(id).build(); + GrpcRDriverDTO response = driverApiBlockingStub.selectByDriverId(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectById"); + return null; + } + return facadeGrpcDriverBuilder.toFacadeBO(response.getData()); + } + + @Override + public FacadePage selectByPage(FacadeDriverQuery query) { + GrpcPageDriverQuery request = facadeGrpcDriverBuilder.toGrpcPageQuery(query); + GrpcRPageDriverDTO response = driverApiBlockingStub.selectByPage(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByPage"); + return FacadePage.empty(); + } + + GrpcPageDriverDTO pageDTO = response.getData(); + List records = pageDTO.getDataList().stream() + .map(facadeGrpcDriverBuilder::toFacadeBO) + .toList(); + + return new FacadePage<>( + pageDTO.getPage().getCurrent(), + pageDTO.getPage().getSize(), + pageDTO.getPage().getTotal(), + pageDTO.getPage().getPages(), + records); + } + + @Override + public FacadeDriverBO selectByDeviceId(Long deviceId) { + GrpcDeviceQuery request = GrpcDeviceQuery.newBuilder().setDeviceId(deviceId).build(); + GrpcRDriverDTO response = driverApiBlockingStub.selectByDeviceId(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByDeviceId"); + return null; + } + return facadeGrpcDriverBuilder.toFacadeBO(response.getData()); + } + + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("DriverGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("DriverFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/PointGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/PointGrpcFacade.java new file mode 100644 index 000000000..91bc31413 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/PointGrpcFacade.java @@ -0,0 +1,95 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.manager.*; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.ManagerConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.PointFacade; +import io.github.pnoker.common.facade.entity.bo.FacadePointBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadePointQuery; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcPointBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * gRPC PointFacade: forwards to Manager Center via + * {@link PointApiGrpc.PointApiBlockingStub}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class PointGrpcFacade implements PointFacade { + + @GrpcClient(ManagerConstant.SERVICE_NAME) + private PointApiGrpc.PointApiBlockingStub pointApiBlockingStub; + + @Resource + private FacadeGrpcPointBuilder facadeGrpcPointBuilder; + + @Override + public FacadePointBO selectById(Long id) { + GrpcPointQuery request = GrpcPointQuery.newBuilder().setPointId(id).build(); + GrpcRPointDTO response = pointApiBlockingStub.selectById(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectById"); + return null; + } + return facadeGrpcPointBuilder.toFacadeBO(response.getData()); + } + + @Override + public FacadePage selectByPage(FacadePointQuery query) { + GrpcPagePointQuery request = facadeGrpcPointBuilder.toGrpcPageQuery(query); + GrpcRPagePointDTO response = pointApiBlockingStub.selectByPage(request); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByPage"); + return FacadePage.empty(); + } + + GrpcPagePointDTO pageDTO = response.getData(); + List records = pageDTO.getDataList().stream() + .map(facadeGrpcPointBuilder::toFacadeBO) + .toList(); + + return new FacadePage<>( + pageDTO.getPage().getCurrent(), + pageDTO.getPage().getSize(), + pageDTO.getPage().getTotal(), + pageDTO.getPage().getPages(), + records); + } + + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("PointGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("PointFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TenantGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TenantGrpcFacade.java new file mode 100644 index 000000000..7ff20ba73 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TenantGrpcFacade.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.auth.GrpcCodeQuery; +import io.github.pnoker.api.center.auth.GrpcRTenantDTO; +import io.github.pnoker.api.center.auth.TenantApiGrpc; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.AuthConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.TenantFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeTenantBO; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcTenantBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +/** + * gRPC {@link TenantFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class TenantGrpcFacade implements TenantFacade { + + @GrpcClient(AuthConstant.SERVICE_NAME) + private TenantApiGrpc.TenantApiBlockingStub tenantApiBlockingStub; + + @Resource + private FacadeGrpcTenantBuilder facadeGrpcTenantBuilder; + + @Override + public FacadeTenantBO selectByCode(String code) { + GrpcRTenantDTO response = tenantApiBlockingStub.selectByCode(GrpcCodeQuery.newBuilder().setCode(code).build()); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByCode"); + return null; + } + return facadeGrpcTenantBuilder.toFacadeBO(response.getData()); + } + + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("TenantGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("TenantFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TokenGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TokenGrpcFacade.java new file mode 100644 index 000000000..c51112c4d --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/TokenGrpcFacade.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.auth.GrpcLoginQuery; +import io.github.pnoker.api.center.auth.GrpcRTokenDTO; +import io.github.pnoker.api.center.auth.TokenApiGrpc; +import io.github.pnoker.common.constant.service.AuthConstant; +import io.github.pnoker.common.facade.api.TokenFacade; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +/** + * gRPC {@link TokenFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class TokenGrpcFacade implements TokenFacade { + + @GrpcClient(AuthConstant.SERVICE_NAME) + private TokenApiGrpc.TokenApiBlockingStub tokenApiBlockingStub; + + @Override + public boolean checkValid(String tenant, String name, String salt, String token) { + GrpcLoginQuery login = GrpcLoginQuery.newBuilder() + .setTenant(tenant) + .setName(name) + .setSalt(salt) + .setToken(token) + .build(); + GrpcRTokenDTO response = tokenApiBlockingStub.checkValid(login); + return response.getResult().getOk(); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserGrpcFacade.java new file mode 100644 index 000000000..0c9ba4edd --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserGrpcFacade.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.auth.GrpcIdQuery; +import io.github.pnoker.api.center.auth.GrpcRUserDTO; +import io.github.pnoker.api.center.auth.UserApiGrpc; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.AuthConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.UserFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeUserBO; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcUserBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +/** + * gRPC {@link UserFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class UserGrpcFacade implements UserFacade { + + @GrpcClient(AuthConstant.SERVICE_NAME) + private UserApiGrpc.UserApiBlockingStub userApiBlockingStub; + + @Resource + private FacadeGrpcUserBuilder facadeGrpcUserBuilder; + + @Override + public FacadeUserBO selectById(Long id) { + GrpcRUserDTO response = userApiBlockingStub.selectById(GrpcIdQuery.newBuilder().setId(id).build()); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectById"); + return null; + } + return facadeGrpcUserBuilder.toFacadeBO(response.getData()); + } + + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("UserGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("UserFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserLoginGrpcFacade.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserLoginGrpcFacade.java new file mode 100644 index 000000000..a469c576a --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/UserLoginGrpcFacade.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc; + +import io.github.pnoker.api.center.auth.GrpcNameQuery; +import io.github.pnoker.api.center.auth.GrpcRUserLoginDTO; +import io.github.pnoker.api.center.auth.UserLoginApiGrpc; +import io.github.pnoker.api.common.GrpcR; +import io.github.pnoker.common.constant.service.AuthConstant; +import io.github.pnoker.common.enums.ResponseEnum; +import io.github.pnoker.common.exception.ServiceException; +import io.github.pnoker.common.facade.api.UserLoginFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeUserLoginBO; +import io.github.pnoker.common.facade.grpc.builder.FacadeGrpcUserLoginBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.client.inject.GrpcClient; +import org.springframework.stereotype.Component; + +/** + * gRPC {@link UserLoginFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class UserLoginGrpcFacade implements UserLoginFacade { + + @GrpcClient(AuthConstant.SERVICE_NAME) + private UserLoginApiGrpc.UserLoginApiBlockingStub userLoginApiBlockingStub; + + @Resource + private FacadeGrpcUserLoginBuilder facadeGrpcUserLoginBuilder; + + @Override + public FacadeUserLoginBO selectByName(String name) { + GrpcRUserLoginDTO response = userLoginApiBlockingStub.selectByName(GrpcNameQuery.newBuilder().setName(name).build()); + if (!response.getResult().getOk()) { + guardOrThrow(response.getResult(), "selectByName"); + return null; + } + return facadeGrpcUserLoginBuilder.toFacadeBO(response.getData()); + } + + private void guardOrThrow(GrpcR result, String op) { + String code = result.getCode(); + if (ResponseEnum.NO_RESOURCE.getCode().equals(code)) { + log.debug("UserLoginGrpcFacade.{} => no resource", op); + return; + } + throw new ServiceException("UserLoginFacade." + op + " failed: [" + code + "] " + result.getMessage()); + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDeviceBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDeviceBuilder.java new file mode 100644 index 000000000..bbc13b45f --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDeviceBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.manager.GrpcPageDeviceQuery; +import io.github.pnoker.api.common.GrpcDeviceDTO; +import io.github.pnoker.api.common.GrpcPage; +import io.github.pnoker.common.constant.common.DefaultConstant; +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.entity.ext.DeviceExt; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO; +import io.github.pnoker.common.facade.entity.query.FacadeDeviceQuery; +import io.github.pnoker.common.optional.LongOptional; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import io.github.pnoker.common.utils.JsonUtil; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +/** + * Converts between {@code dc3-common-facade-api} shapes and the protobuf types + * generated from {@code api/center/manager/manager_device.proto}. + *

+ * Hand-rolled rather than MapStruct because protobuf builders expose dozens of + * generated accessors ({@code mergeFrom}, {@code clearField}, {@code *Bytes}, ...) + * that would each need an explicit {@code @Mapping(target = "...", ignore = true)}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcDeviceBuilder { + + public GrpcPageDeviceQuery toGrpcPageQuery(FacadeDeviceQuery query) { + GrpcPageDeviceQuery.Builder builder = GrpcPageDeviceQuery.newBuilder(); + + Pages pages = Objects.isNull(query.getPage()) ? new Pages() : query.getPage(); + GrpcPage.Builder page = GrpcPage.newBuilder() + .setCurrent(pages.getCurrent()) + .setSize(pages.getSize()); + builder.setPage(page); + + LongOptional.ofNullable(query.getTenantId()).ifPresent(builder::setTenantId); + StringOptional.ofNullable(query.getDeviceName()).ifPresent(builder::setDeviceName); + StringOptional.ofNullable(query.getDeviceCode()).ifPresent(builder::setDeviceCode); + LongOptional.ofNullable(query.getDriverId()).ifPresent(builder::setDriverId); + LongOptional.ofNullable(query.getProfileId()).ifPresent(builder::setProfileId); + Optional.ofNullable(query.getEnableFlag()).ifPresentOrElse( + value -> builder.setEnableFlag(value.getIndex()), + () -> builder.setEnableFlag(DefaultConstant.DEFAULT_INT) + ); + + return builder.build(); + } + + public FacadeDeviceBO toFacadeBO(GrpcDeviceDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadeDeviceBO bo = new FacadeDeviceBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getDeviceName()).ifPresent(bo::setDeviceName); + StringOptional.ofNullable(dto.getDeviceCode()).ifPresent(bo::setDeviceCode); + LongOptional.ofNullable(dto.getDriverId()).ifPresent(bo::setDriverId); + StringOptional.ofNullable(dto.getSignature()).ifPresent(bo::setSignature); + LongOptional.ofNullable(dto.getTenantId()).ifPresent(bo::setTenantId); + + if (dto.getVersion() != DefaultConstant.DEFAULT_INT) { + bo.setVersion(dto.getVersion()); + } + + byte enableIndex = (byte) dto.getEnableFlag(); + Optional.ofNullable(EnableFlagEnum.ofIndex(enableIndex)).ifPresent(bo::setEnableFlag); + + StringOptional.ofNullable(dto.getDeviceExt()) + .ifPresent(value -> bo.setDeviceExt(JsonUtil.parseObject(value, DeviceExt.class))); + + if (dto.getProfileIdsCount() > 0) { + bo.setProfileIds(new ArrayList<>(dto.getProfileIdsList())); + } + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDriverBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDriverBuilder.java new file mode 100644 index 000000000..d3b8f3e51 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcDriverBuilder.java @@ -0,0 +1,108 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.manager.GrpcPageDriverQuery; +import io.github.pnoker.api.common.GrpcDriverDTO; +import io.github.pnoker.api.common.GrpcPage; +import io.github.pnoker.common.constant.common.DefaultConstant; +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.entity.ext.DriverExt; +import io.github.pnoker.common.enums.DriverTypeFlagEnum; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO; +import io.github.pnoker.common.facade.entity.query.FacadeDriverQuery; +import io.github.pnoker.common.optional.LongOptional; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import io.github.pnoker.common.utils.JsonUtil; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +/** + * Hand-rolled conversion between facade shapes and protobuf driver types. + *

+ * Driver uses {@code NULL_INT = -1} as the "not set" marker for + * {@code driverTypeFlag} (unlike Device, which piggy-backs on {@code DEFAULT_INT = 0}). + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcDriverBuilder { + + public GrpcPageDriverQuery toGrpcPageQuery(FacadeDriverQuery query) { + GrpcPageDriverQuery.Builder builder = GrpcPageDriverQuery.newBuilder(); + + Pages pages = Objects.isNull(query.getPage()) ? new Pages() : query.getPage(); + GrpcPage.Builder page = GrpcPage.newBuilder() + .setCurrent(pages.getCurrent()) + .setSize(pages.getSize()); + builder.setPage(page); + + LongOptional.ofNullable(query.getTenantId()).ifPresent(builder::setTenantId); + StringOptional.ofNullable(query.getDriverName()).ifPresent(builder::setDriverName); + StringOptional.ofNullable(query.getDriverCode()).ifPresent(builder::setDriverCode); + StringOptional.ofNullable(query.getServiceName()).ifPresent(builder::setServiceName); + StringOptional.ofNullable(query.getServiceHost()).ifPresent(builder::setServiceHost); + Optional.ofNullable(query.getDriverTypeFlag()).ifPresentOrElse( + value -> builder.setDriverTypeFlag(value.getIndex()), + () -> builder.setDriverTypeFlag(DefaultConstant.NULL_INT) + ); + Optional.ofNullable(query.getEnableFlag()).ifPresentOrElse( + value -> builder.setEnableFlag(value.getIndex()), + () -> builder.setEnableFlag(DefaultConstant.DEFAULT_INT) + ); + + return builder.build(); + } + + public FacadeDriverBO toFacadeBO(GrpcDriverDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadeDriverBO bo = new FacadeDriverBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getDriverName()).ifPresent(bo::setDriverName); + StringOptional.ofNullable(dto.getDriverCode()).ifPresent(bo::setDriverCode); + StringOptional.ofNullable(dto.getServiceName()).ifPresent(bo::setServiceName); + StringOptional.ofNullable(dto.getServiceHost()).ifPresent(bo::setServiceHost); + StringOptional.ofNullable(dto.getSignature()).ifPresent(bo::setSignature); + LongOptional.ofNullable(dto.getTenantId()).ifPresent(bo::setTenantId); + + if (dto.getVersion() != DefaultConstant.DEFAULT_INT) { + bo.setVersion(dto.getVersion()); + } + + int driverType = dto.getDriverTypeFlag(); + if (driverType != DefaultConstant.NULL_INT) { + Optional.ofNullable(DriverTypeFlagEnum.ofIndex((byte) driverType)).ifPresent(bo::setDriverTypeFlag); + } + + Optional.ofNullable(EnableFlagEnum.ofIndex((byte) dto.getEnableFlag())).ifPresent(bo::setEnableFlag); + + StringOptional.ofNullable(dto.getDriverExt()) + .ifPresent(value -> bo.setDriverExt(JsonUtil.parseObject(value, DriverExt.class))); + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcPointBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcPointBuilder.java new file mode 100644 index 000000000..95dcbf6b6 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcPointBuilder.java @@ -0,0 +1,132 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.manager.GrpcPagePointQuery; +import io.github.pnoker.api.common.GrpcPage; +import io.github.pnoker.api.common.GrpcPointDTO; +import io.github.pnoker.common.constant.common.DefaultConstant; +import io.github.pnoker.common.entity.common.Pages; +import io.github.pnoker.common.entity.ext.PointExt; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.enums.PointTypeFlagEnum; +import io.github.pnoker.common.enums.RwFlagEnum; +import io.github.pnoker.common.facade.entity.bo.FacadePointBO; +import io.github.pnoker.common.facade.entity.query.FacadePointQuery; +import io.github.pnoker.common.optional.LongOptional; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import io.github.pnoker.common.utils.JsonUtil; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.Objects; +import java.util.Optional; + +/** + * Hand-rolled conversion between facade shapes and protobuf point types. + *

+ * {@code baseValue} / {@code multiple} are {@link BigDecimal} on the Java side but + * {@code double} on the wire — precision loss is inherited from the existing proto + * contract, not introduced here. + *

+ * Uses {@link DefaultConstant#NULL_INT NULL_INT} as "not set" for + * {@code pointTypeFlag} / {@code rwFlag} / {@code profileId}, matching + * {@code GrpcPointBuilder}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcPointBuilder { + + public GrpcPagePointQuery toGrpcPageQuery(FacadePointQuery query) { + GrpcPagePointQuery.Builder builder = GrpcPagePointQuery.newBuilder(); + + Pages pages = Objects.isNull(query.getPage()) ? new Pages() : query.getPage(); + GrpcPage.Builder page = GrpcPage.newBuilder() + .setCurrent(pages.getCurrent()) + .setSize(pages.getSize()); + builder.setPage(page); + + LongOptional.ofNullable(query.getTenantId()).ifPresent(builder::setTenantId); + StringOptional.ofNullable(query.getPointName()).ifPresent(builder::setPointName); + StringOptional.ofNullable(query.getPointCode()).ifPresent(builder::setPointCode); + LongOptional.ofNullable(query.getDeviceId()).ifPresent(builder::setDeviceId); + + Optional.ofNullable(query.getPointTypeFlag()).ifPresentOrElse( + value -> builder.setPointTypeFlag(value.getIndex()), + () -> builder.setPointTypeFlag(DefaultConstant.NULL_INT) + ); + Optional.ofNullable(query.getRwFlag()).ifPresentOrElse( + value -> builder.setRwFlag(value.getIndex()), + () -> builder.setRwFlag(DefaultConstant.NULL_INT) + ); + Optional.ofNullable(query.getProfileId()).ifPresentOrElse( + builder::setProfileId, + () -> builder.setProfileId(DefaultConstant.NULL_INT) + ); + Optional.ofNullable(query.getEnableFlag()).ifPresentOrElse( + value -> builder.setEnableFlag(value.getIndex()), + () -> builder.setEnableFlag(DefaultConstant.DEFAULT_INT) + ); + + return builder.build(); + } + + public FacadePointBO toFacadeBO(GrpcPointDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadePointBO bo = new FacadePointBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getPointName()).ifPresent(bo::setPointName); + StringOptional.ofNullable(dto.getPointCode()).ifPresent(bo::setPointCode); + StringOptional.ofNullable(dto.getUnit()).ifPresent(bo::setUnit); + StringOptional.ofNullable(dto.getSignature()).ifPresent(bo::setSignature); + LongOptional.ofNullable(dto.getTenantId()).ifPresent(bo::setTenantId); + LongOptional.ofNullable(dto.getProfileId()).ifPresent(bo::setProfileId); + + bo.setBaseValue(BigDecimal.valueOf(dto.getBaseValue())); + bo.setMultiple(BigDecimal.valueOf(dto.getMultiple())); + bo.setValueDecimal((byte) dto.getValueDecimal()); + + if (dto.getVersion() != DefaultConstant.DEFAULT_INT) { + bo.setVersion(dto.getVersion()); + } + + int pointType = dto.getPointTypeFlag(); + if (pointType != DefaultConstant.NULL_INT) { + Optional.ofNullable(PointTypeFlagEnum.ofIndex((byte) pointType)).ifPresent(bo::setPointTypeFlag); + } + + int rw = dto.getRwFlag(); + if (rw != DefaultConstant.NULL_INT) { + Optional.ofNullable(RwFlagEnum.ofIndex((byte) rw)).ifPresent(bo::setRwFlag); + } + + Optional.ofNullable(EnableFlagEnum.ofIndex((byte) dto.getEnableFlag())).ifPresent(bo::setEnableFlag); + + StringOptional.ofNullable(dto.getPointExt()) + .ifPresent(value -> bo.setPointExt(JsonUtil.parseObject(value, PointExt.class))); + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcTenantBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcTenantBuilder.java new file mode 100644 index 000000000..03a77e191 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcTenantBuilder.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.auth.GrpcTenantDTO; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.facade.entity.bo.FacadeTenantBO; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +/** + * {@code GrpcTenantDTO} → {@link FacadeTenantBO}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcTenantBuilder { + + public FacadeTenantBO toFacadeBO(GrpcTenantDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadeTenantBO bo = new FacadeTenantBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getTenantName()).ifPresent(bo::setTenantName); + StringOptional.ofNullable(dto.getTenantCode()).ifPresent(bo::setTenantCode); + Optional.ofNullable(EnableFlagEnum.ofIndex((byte) dto.getEnableFlag())).ifPresent(bo::setEnableFlag); + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserBuilder.java new file mode 100644 index 000000000..b3be72d37 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.auth.GrpcUserDTO; +import io.github.pnoker.common.facade.entity.bo.FacadeUserBO; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * {@code GrpcUserDTO} → {@link FacadeUserBO}. {@code socialExt}/{@code identityExt} + * stay as opaque JSON strings — keeping the wire representation untouched. + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcUserBuilder { + + public FacadeUserBO toFacadeBO(GrpcUserDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadeUserBO bo = new FacadeUserBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getNickName()).ifPresent(bo::setNickName); + StringOptional.ofNullable(dto.getUserName()).ifPresent(bo::setUserName); + StringOptional.ofNullable(dto.getPhone()).ifPresent(bo::setPhone); + StringOptional.ofNullable(dto.getEmail()).ifPresent(bo::setEmail); + StringOptional.ofNullable(dto.getSocialExt()).ifPresent(bo::setSocialExt); + StringOptional.ofNullable(dto.getIdentityExt()).ifPresent(bo::setIdentityExt); + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserLoginBuilder.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserLoginBuilder.java new file mode 100644 index 000000000..e9ced1e69 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/builder/FacadeGrpcUserLoginBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.builder; + +import io.github.pnoker.api.center.auth.GrpcUserLoginDTO; +import io.github.pnoker.common.enums.EnableFlagEnum; +import io.github.pnoker.common.facade.entity.bo.FacadeUserLoginBO; +import io.github.pnoker.common.optional.LongOptional; +import io.github.pnoker.common.optional.StringOptional; +import io.github.pnoker.common.utils.GrpcBuilderUtil; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +/** + * {@code GrpcUserLoginDTO} → {@link FacadeUserLoginBO}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Component +public class FacadeGrpcUserLoginBuilder { + + public FacadeUserLoginBO toFacadeBO(GrpcUserLoginDTO dto) { + if (Objects.isNull(dto)) { + return null; + } + + FacadeUserLoginBO bo = new FacadeUserLoginBO(); + GrpcBuilderUtil.buildBaseBOByGrpcBase(dto.getBase(), bo); + + StringOptional.ofNullable(dto.getLoginName()).ifPresent(bo::setLoginName); + LongOptional.ofNullable(dto.getUserId()).ifPresent(bo::setUserId); + LongOptional.ofNullable(dto.getUserPasswordId()).ifPresent(bo::setUserPasswordId); + Optional.ofNullable(EnableFlagEnum.ofIndex((byte) dto.getEnableFlag())).ifPresent(bo::setEnableFlag); + + return bo; + } +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/config/GrpcFacadeAutoConfiguration.java b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/config/GrpcFacadeAutoConfiguration.java new file mode 100644 index 000000000..9c274a007 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/java/io/github/pnoker/common/facade/grpc/config/GrpcFacadeAutoConfiguration.java @@ -0,0 +1,37 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.grpc.config; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.ComponentScan; + +/** + * Auto-configuration for the gRPC facade implementation. Active by default + * (when {@code dc3.facade.mode} is absent) or when explicitly set to + * {@code grpc}. Scans the facade-grpc package so the {@code @Component} beans + * are registered. + * + * @author pnoker + * @since 2026.4.19 + */ +@AutoConfiguration +@ConditionalOnProperty(name = "dc3.facade.mode", havingValue = "grpc", matchIfMissing = true) +@ComponentScan("io.github.pnoker.common.facade.grpc") +public class GrpcFacadeAutoConfiguration { +} diff --git a/dc3-common/dc3-common-facade-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dc3-common/dc3-common-facade-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..e010b2397 --- /dev/null +++ b/dc3-common/dc3-common-facade-grpc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,18 @@ +# +# Copyright 2016-present the IoT DC3 original author or authors. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +io.github.pnoker.common.facade.grpc.config.GrpcFacadeAutoConfiguration diff --git a/dc3-common/dc3-common-facade-local/pom.xml b/dc3-common/dc3-common-facade-local/pom.xml new file mode 100644 index 000000000..a2ada00dd --- /dev/null +++ b/dc3-common/dc3-common-facade-local/pom.xml @@ -0,0 +1,58 @@ + + + + 4.0.0 + + + io.github.pnoker + dc3-common + 2026.4.19 + + + ${project.artifactId} + dc3-common-facade-local + 2026.4.19 + jar + + 2016 + https://github.com/pnoker/iot-dc3 + + Local (in-process) implementation of the Facade API, selected when + dc3.facade.mode=local. Directly invokes manager services without gRPC. + + + + + + + io.github.pnoker + dc3-common-facade-api + + + io.github.pnoker + dc3-common-auth + + + io.github.pnoker + dc3-common-manager + + + + + diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DeviceLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DeviceLocalFacade.java new file mode 100644 index 000000000..12ead1c5a --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DeviceLocalFacade.java @@ -0,0 +1,93 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.github.pnoker.common.facade.api.DeviceFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDeviceQuery; +import io.github.pnoker.common.facade.local.builder.FacadeDeviceBuilder; +import io.github.pnoker.common.manager.entity.bo.DeviceBO; +import io.github.pnoker.common.manager.entity.query.DeviceQuery; +import io.github.pnoker.common.manager.service.DeviceService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * In-process implementation: routes each call straight into {@link DeviceService}. + *

+ * Selected when {@code dc3.facade.mode=local}. Carries zero serialization cost + * — the same JVM handles both caller and service. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class DeviceLocalFacade implements DeviceFacade { + + @Resource + private DeviceService deviceService; + + @Resource + private FacadeDeviceBuilder facadeDeviceBuilder; + + @Override + public FacadeDeviceBO selectById(Long id) { + DeviceBO managerBO = deviceService.selectById(id); + return Objects.isNull(managerBO) ? null : facadeDeviceBuilder.toFacadeBO(managerBO); + } + + @Override + public FacadePage selectByPage(FacadeDeviceQuery query) { + DeviceQuery managerQuery = facadeDeviceBuilder.toManagerQuery(query); + Page page = deviceService.selectByPage(managerQuery); + if (Objects.isNull(page)) { + return FacadePage.empty(); + } + + List records = page.getRecords().stream() + .map(facadeDeviceBuilder::toFacadeBO) + .toList(); + return new FacadePage<>(page.getCurrent(), page.getSize(), page.getTotal(), page.getPages(), records); + } + + @Override + public List selectByProfileId(Long profileId) { + List list = deviceService.selectByProfileId(profileId); + if (Objects.isNull(list) || list.isEmpty()) { + return Collections.emptyList(); + } + return list.stream().map(facadeDeviceBuilder::toFacadeBO).toList(); + } + + @Override + public List selectByDriverId(Long driverId) { + List list = deviceService.selectByDriverId(driverId); + if (Objects.isNull(list) || list.isEmpty()) { + return Collections.emptyList(); + } + return list.stream().map(facadeDeviceBuilder::toFacadeBO).toList(); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DriverLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DriverLocalFacade.java new file mode 100644 index 000000000..375497a42 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/DriverLocalFacade.java @@ -0,0 +1,77 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.github.pnoker.common.facade.api.DriverFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadeDriverQuery; +import io.github.pnoker.common.facade.local.builder.FacadeDriverBuilder; +import io.github.pnoker.common.manager.entity.bo.DriverBO; +import io.github.pnoker.common.manager.entity.query.DriverQuery; +import io.github.pnoker.common.manager.service.DriverService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * In-process DriverFacade implementation. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class DriverLocalFacade implements DriverFacade { + + @Resource + private DriverService driverService; + + @Resource + private FacadeDriverBuilder facadeDriverBuilder; + + @Override + public FacadeDriverBO selectById(Long id) { + DriverBO managerBO = driverService.selectById(id); + return Objects.isNull(managerBO) ? null : facadeDriverBuilder.toFacadeBO(managerBO); + } + + @Override + public FacadePage selectByPage(FacadeDriverQuery query) { + DriverQuery managerQuery = facadeDriverBuilder.toManagerQuery(query); + Page page = driverService.selectByPage(managerQuery); + if (Objects.isNull(page)) { + return FacadePage.empty(); + } + + List records = page.getRecords().stream() + .map(facadeDriverBuilder::toFacadeBO) + .toList(); + return new FacadePage<>(page.getCurrent(), page.getSize(), page.getTotal(), page.getPages(), records); + } + + @Override + public FacadeDriverBO selectByDeviceId(Long deviceId) { + DriverBO managerBO = driverService.selectByDeviceId(deviceId); + return Objects.isNull(managerBO) ? null : facadeDriverBuilder.toFacadeBO(managerBO); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/PointLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/PointLocalFacade.java new file mode 100644 index 000000000..e4f6dfb00 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/PointLocalFacade.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.github.pnoker.common.facade.api.PointFacade; +import io.github.pnoker.common.facade.entity.bo.FacadePointBO; +import io.github.pnoker.common.facade.entity.common.FacadePage; +import io.github.pnoker.common.facade.entity.query.FacadePointQuery; +import io.github.pnoker.common.facade.local.builder.FacadePointBuilder; +import io.github.pnoker.common.manager.entity.bo.PointBO; +import io.github.pnoker.common.manager.entity.query.PointQuery; +import io.github.pnoker.common.manager.service.PointService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * In-process PointFacade implementation. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class PointLocalFacade implements PointFacade { + + @Resource + private PointService pointService; + + @Resource + private FacadePointBuilder facadePointBuilder; + + @Override + public FacadePointBO selectById(Long id) { + PointBO managerBO = pointService.selectById(id); + return Objects.isNull(managerBO) ? null : facadePointBuilder.toFacadeBO(managerBO); + } + + @Override + public FacadePage selectByPage(FacadePointQuery query) { + PointQuery managerQuery = facadePointBuilder.toManagerQuery(query); + Page page = pointService.selectByPage(managerQuery); + if (Objects.isNull(page)) { + return FacadePage.empty(); + } + + List records = page.getRecords().stream() + .map(facadePointBuilder::toFacadeBO) + .toList(); + return new FacadePage<>(page.getCurrent(), page.getSize(), page.getTotal(), page.getPages(), records); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TenantLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TenantLocalFacade.java new file mode 100644 index 000000000..e4ead6229 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TenantLocalFacade.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import io.github.pnoker.common.auth.entity.bo.TenantBO; +import io.github.pnoker.common.auth.service.TenantService; +import io.github.pnoker.common.facade.api.TenantFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeTenantBO; +import io.github.pnoker.common.facade.local.builder.FacadeTenantBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * In-process {@link TenantFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class TenantLocalFacade implements TenantFacade { + + @Resource + private TenantService tenantService; + + @Resource + private FacadeTenantBuilder facadeTenantBuilder; + + @Override + public FacadeTenantBO selectByCode(String code) { + TenantBO bo = tenantService.selectByCode(code); + return Objects.isNull(bo) ? null : facadeTenantBuilder.toFacadeBO(bo); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TokenLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TokenLocalFacade.java new file mode 100644 index 000000000..dd8f73aa7 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/TokenLocalFacade.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import io.github.pnoker.common.auth.biz.TokenService; +import io.github.pnoker.common.auth.entity.bean.TokenValid; +import io.github.pnoker.common.facade.api.TokenFacade; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * In-process {@link TokenFacade}. Collapses the three-way outcome of + * {@code TokenService.checkValid} (null / invalid / valid) into a boolean. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class TokenLocalFacade implements TokenFacade { + + @Resource + private TokenService tokenService; + + @Override + public boolean checkValid(String tenant, String name, String salt, String token) { + TokenValid entity = tokenService.checkValid(name, salt, token, tenant); + return Objects.nonNull(entity) && entity.isValid(); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLocalFacade.java new file mode 100644 index 000000000..0007a1420 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLocalFacade.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import io.github.pnoker.common.auth.entity.bo.UserBO; +import io.github.pnoker.common.auth.service.UserService; +import io.github.pnoker.common.facade.api.UserFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeUserBO; +import io.github.pnoker.common.facade.local.builder.FacadeUserBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * In-process {@link UserFacade}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class UserLocalFacade implements UserFacade { + + @Resource + private UserService userService; + + @Resource + private FacadeUserBuilder facadeUserBuilder; + + @Override + public FacadeUserBO selectById(Long id) { + UserBO bo = userService.selectById(id); + return Objects.isNull(bo) ? null : facadeUserBuilder.toFacadeBO(bo); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLoginLocalFacade.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLoginLocalFacade.java new file mode 100644 index 000000000..98194a6f6 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/UserLoginLocalFacade.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local; + +import io.github.pnoker.common.auth.entity.bo.UserLoginBO; +import io.github.pnoker.common.auth.service.UserLoginService; +import io.github.pnoker.common.facade.api.UserLoginFacade; +import io.github.pnoker.common.facade.entity.bo.FacadeUserLoginBO; +import io.github.pnoker.common.facade.local.builder.FacadeUserLoginBuilder; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * In-process {@link UserLoginFacade}. Matches {@code UserLoginServer} which + * also calls {@code selectByLoginName(name, false)}. + * + * @author pnoker + * @since 2026.4.19 + */ +@Slf4j +@Component +public class UserLoginLocalFacade implements UserLoginFacade { + + @Resource + private UserLoginService userLoginService; + + @Resource + private FacadeUserLoginBuilder facadeUserLoginBuilder; + + @Override + public FacadeUserLoginBO selectByName(String name) { + UserLoginBO bo = userLoginService.selectByLoginName(name, false); + return Objects.isNull(bo) ? null : facadeUserLoginBuilder.toFacadeBO(bo); + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDeviceBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDeviceBuilder.java new file mode 100644 index 000000000..c04591b55 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDeviceBuilder.java @@ -0,0 +1,40 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.facade.entity.bo.FacadeDeviceBO; +import io.github.pnoker.common.facade.entity.query.FacadeDeviceQuery; +import io.github.pnoker.common.manager.entity.bo.DeviceBO; +import io.github.pnoker.common.manager.entity.query.DeviceQuery; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.Mapper; + +/** + * Converts between the facade-api shapes and {@code dc3-common-manager} internals. + * Field sets are aligned by design, so MapStruct auto-maps every property. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadeDeviceBuilder { + + DeviceQuery toManagerQuery(FacadeDeviceQuery facadeQuery); + + FacadeDeviceBO toFacadeBO(DeviceBO managerBO); +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDriverBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDriverBuilder.java new file mode 100644 index 000000000..6cd2ed590 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeDriverBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.facade.entity.bo.FacadeDriverBO; +import io.github.pnoker.common.facade.entity.query.FacadeDriverQuery; +import io.github.pnoker.common.manager.entity.bo.DriverBO; +import io.github.pnoker.common.manager.entity.query.DriverQuery; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.Mapper; + +/** + * FacadeDriver ↔ manager DriverBO/Query mapper. Field sets are aligned. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadeDriverBuilder { + + DriverQuery toManagerQuery(FacadeDriverQuery facadeQuery); + + FacadeDriverBO toFacadeBO(DriverBO managerBO); +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadePointBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadePointBuilder.java new file mode 100644 index 000000000..2d613973c --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadePointBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.facade.entity.bo.FacadePointBO; +import io.github.pnoker.common.facade.entity.query.FacadePointQuery; +import io.github.pnoker.common.manager.entity.bo.PointBO; +import io.github.pnoker.common.manager.entity.query.PointQuery; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.Mapper; + +/** + * FacadePoint ↔ manager PointBO/Query mapper. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadePointBuilder { + + PointQuery toManagerQuery(FacadePointQuery facadeQuery); + + FacadePointBO toFacadeBO(PointBO managerBO); +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeTenantBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeTenantBuilder.java new file mode 100644 index 000000000..e0c58e178 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeTenantBuilder.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.auth.entity.bo.TenantBO; +import io.github.pnoker.common.facade.entity.bo.FacadeTenantBO; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.Mapper; + +/** + * FacadeTenant ↔ auth TenantBO mapper. {@code tenantExt} is absent from the + * facade shape and therefore dropped by MapStruct. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadeTenantBuilder { + + FacadeTenantBO toFacadeBO(TenantBO authBO); +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserBuilder.java new file mode 100644 index 000000000..392befc1f --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserBuilder.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.auth.entity.bo.UserBO; +import io.github.pnoker.common.entity.ext.UserIdentityExt; +import io.github.pnoker.common.entity.ext.UserSocialExt; +import io.github.pnoker.common.facade.entity.bo.FacadeUserBO; +import io.github.pnoker.common.utils.JsonUtil; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; + +import java.util.Objects; + +/** + * FacadeUser ↔ auth UserBO mapper. + *

+ * {@code UserBO} carries typed {@code UserSocialExt}/{@code UserIdentityExt} + * objects, while the facade contract (matching {@code GrpcUserDTO}) carries + * their JSON forms, so these two fields need an explicit conversion. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadeUserBuilder { + + @Mapping(target = "socialExt", ignore = true) + @Mapping(target = "identityExt", ignore = true) + FacadeUserBO toFacadeBO(UserBO authBO); + + @AfterMapping + default void afterProcess(UserBO authBO, @MappingTarget FacadeUserBO facadeBO) { + UserSocialExt social = authBO.getSocialExt(); + if (Objects.nonNull(social)) { + facadeBO.setSocialExt(JsonUtil.toJsonString(social)); + } + + UserIdentityExt identity = authBO.getIdentityExt(); + if (Objects.nonNull(identity)) { + facadeBO.setIdentityExt(JsonUtil.toJsonString(identity)); + } + } +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserLoginBuilder.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserLoginBuilder.java new file mode 100644 index 000000000..21a92d494 --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/builder/FacadeUserLoginBuilder.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.builder; + +import io.github.pnoker.common.auth.entity.bo.UserLoginBO; +import io.github.pnoker.common.facade.entity.bo.FacadeUserLoginBO; +import io.github.pnoker.common.utils.MapStructUtil; +import org.mapstruct.Mapper; + +/** + * FacadeUserLogin ↔ auth UserLoginBO mapper. + * + * @author pnoker + * @since 2026.4.19 + */ +@Mapper(componentModel = "spring", uses = {MapStructUtil.class}) +public interface FacadeUserLoginBuilder { + + FacadeUserLoginBO toFacadeBO(UserLoginBO authBO); +} diff --git a/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/config/LocalFacadeAutoConfiguration.java b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/config/LocalFacadeAutoConfiguration.java new file mode 100644 index 000000000..fe362cc1f --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/java/io/github/pnoker/common/facade/local/config/LocalFacadeAutoConfiguration.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-present the IoT DC3 original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.github.pnoker.common.facade.local.config; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.ComponentScan; + +/** + * Auto-configuration for the local facade implementation. Active only when + * {@code dc3.facade.mode=local}. Scans the facade-local package so the + * {@code @Component}/{@code @Mapper} beans are registered. + * + * @author pnoker + * @since 2026.4.19 + */ +@AutoConfiguration +@ConditionalOnProperty(name = "dc3.facade.mode", havingValue = "local") +@ComponentScan("io.github.pnoker.common.facade.local") +public class LocalFacadeAutoConfiguration { +} diff --git a/dc3-common/dc3-common-facade-local/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dc3-common/dc3-common-facade-local/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..426fa161f --- /dev/null +++ b/dc3-common/dc3-common-facade-local/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,18 @@ +# +# Copyright 2016-present the IoT DC3 original author or authors. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +io.github.pnoker.common.facade.local.config.LocalFacadeAutoConfiguration diff --git a/dc3-common/pom.xml b/dc3-common/pom.xml index c077b02d5..91d466739 100644 --- a/dc3-common/pom.xml +++ b/dc3-common/pom.xml @@ -82,6 +82,9 @@ dc3-common-data dc3-common-driver dc3-common-exception + dc3-common-facade-api + dc3-common-facade-grpc + dc3-common-facade-local dc3-common-gateway dc3-common-log dc3-common-manager @@ -213,6 +216,21 @@ dc3-common-exception ${dc3.version} + + io.github.pnoker + dc3-common-facade-api + ${dc3.version} + + + io.github.pnoker + dc3-common-facade-grpc + ${dc3.version} + + + io.github.pnoker + dc3-common-facade-local + ${dc3.version} + io.github.pnoker dc3-common-gateway diff --git a/pom.xml b/pom.xml index 5e32d18d8..636db41cf 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,21 @@ dc3-common-exception ${dc3.version} + + io.github.pnoker + dc3-common-facade-api + ${dc3.version} + + + io.github.pnoker + dc3-common-facade-grpc + ${dc3.version} + + + io.github.pnoker + dc3-common-facade-local + ${dc3.version} + io.github.pnoker dc3-common-gateway