From d84f642b558f5c633807274ec85ec808c0560dab Mon Sep 17 00:00:00 2001 From: Kaveesha Date: Wed, 7 Jul 2021 00:55:27 +0530 Subject: [PATCH] Add API for get app subscribed device list from a subscription group --- .../common/services/SubscriptionManager.java | 12 ++ .../mgt/core/dao/SubscriptionDAO.java | 12 ++ .../GenericSubscriptionDAOImpl.java | 41 +++++ .../core/impl/SubscriptionManagerImpl.java | 46 ++++++ .../services/SubscriptionManagementAPI.java | 97 +++++++++++ .../impl/SubscriptionManagementAPIImpl.java | 69 ++++++++ .../carbon/device/mgt/core/dao/DeviceDAO.java | 23 +++ .../core/dao/impl/AbstractDeviceDAOImpl.java | 150 ++++++++++++++++++ .../dao/impl/device/OracleDeviceDAOImpl.java | 73 +++++++++ .../impl/device/SQLServerDeviceDAOImpl.java | 74 +++++++++ .../DeviceManagementProviderService.java | 10 ++ .../DeviceManagementProviderServiceImpl.java | 35 ++++ 12 files changed, 642 insertions(+) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java index a535ffd3897..600da94b4f4 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/services/SubscriptionManager.java @@ -161,4 +161,16 @@ public interface SubscriptionManager { */ PaginationResult getAppSubscriptionDetails(PaginationRequest request, String appUUID, String actionStatus, String action) throws ApplicationManagementException; + + /*** + * This method is responsible to provide application subscription devices data for given application release UUID. + * @param request PaginationRequest object holding the data for pagination + * @param appUUID UUID of the application release. + * @param subType subscription type of the application(eg: GROUP, USER, ...) + * @param subTypeName subscription type name of the application (Name of the group, Name of the user, ...). + * @return {@link PaginationResult} pagination result of the category details. + * @throws {@link ApplicationManagementException} Exception of the application management + */ + PaginationResult getAppInstalledSubscribeDevices(PaginationRequest request, String appUUID, String subType, + String subTypeName) throws ApplicationManagementException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java index ce8780a6a28..3ff0d95945d 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java @@ -228,4 +228,16 @@ public interface SubscriptionDAO { throws ApplicationManagementDAOException; int getSubscribedGroupCount(int appReleaseId, int tenantId) throws ApplicationManagementDAOException; + + /** + * This method is used to get the details of subscribed groups + * + * @param tenantId id of the current tenant + * @param appReleaseId id of the application release.. + * @param subtype application subscribed type. + * @return subscribedDevices - list of app subscribed devices under the subtype. + * @throws {@link ApplicationManagementDAOException} if connections establishment fails. + */ + List getAppSubscribedDevicesForGroups(int appReleaseId, String subtype, int tenantId) + throws ApplicationManagementDAOException; } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java index c2fd7f240a5..4e6c6623f16 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java @@ -1271,4 +1271,45 @@ public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements Subsc throw new ApplicationManagementDAOException(msg, e); } } + + @Override + public List getAppSubscribedDevicesForGroups(int appReleaseId, String subType, int tenantId) + throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get already subscribed devices for " + + "given app release id."); + } + // retrieve all device list by action triggered type and app release id + try { + Connection conn = this.getDBConnection(); + List subscribedGroupDevices = new ArrayList<>(); + String sql = "SELECT " + + "AP_DEVICE_SUBSCRIPTION.DM_DEVICE_ID AS DEVICES " + + "FROM AP_DEVICE_SUBSCRIPTION " + + "WHERE " + + "AP_APP_RELEASE_ID = ? AND ACTION_TRIGGERED_FROM=? AND " + + "UNSUBSCRIBED=FALSE AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setInt(1, appReleaseId); + ps.setString(2, subType.toLowerCase());; + ps.setInt(3, tenantId); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + subscribedGroupDevices.add(rs.getInt("DEVICES")); + } + } + return subscribedGroupDevices; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get already " + + "subscribed groups for given app release id."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while getting subscribed devices for given " + + "app release id."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java index 5aa222ce13f..8219dbb4e76 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java @@ -1427,4 +1427,50 @@ public class SubscriptionManagerImpl implements SubscriptionManager { ConnectionManagerUtil.closeDBConnection(); } } + + @Override + public PaginationResult getAppInstalledSubscribeDevices(PaginationRequest request, String appUUID, String subType, + String subTypeName) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + DeviceManagementProviderService deviceManagementProviderService = HelperUtil + .getDeviceManagementProviderService(); + try { + ConnectionManagerUtil.openDBConnection(); + ApplicationDTO applicationDTO = this.applicationDAO.getAppWithRelatedRelease(appUUID, tenantId); + int applicationReleaseId = applicationDTO.getApplicationReleaseDTOs().get(0).getId(); + List subscriptionDeviceList = new ArrayList<>(); + //todo update the API for other subscription types + if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) { + subscriptionDeviceList = subscriptionDAO + .getAppSubscribedDevicesForGroups(applicationReleaseId, subType, tenantId); + } else { + String msg = "Found invalid sub type: " + subType; + log.error(msg); + throw new NotFoundException(msg); + } + if (subscriptionDeviceList.isEmpty()) { + PaginationResult paginationResult = new PaginationResult(); + paginationResult.setData(subscriptionDeviceList); + paginationResult.setRecordsFiltered(0); + paginationResult.setRecordsTotal(0); + return paginationResult; + } + return deviceManagementProviderService.getDevicesDetails(request, subscriptionDeviceList, subTypeName); + } catch (DeviceManagementException e) { + String msg = "service error occurred while getting device data from the device management service."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred when get application release devices data for application release UUID: " + + appUUID; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "DB Connection error occurred while getting category details that given application id"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java index be55b64639a..2c8811358d7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/SubscriptionManagementAPI.java @@ -446,4 +446,101 @@ public interface SubscriptionManagementAPI { defaultValue = "5") @QueryParam("limit") int limit ); + + @GET + @Path("/{uuid}/{subType}/{subTypeName}/devices") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Get device details in categories that have a given application install", + notes = "This will get the category's device details that have a given application install, if exists", + tags = "Subscription Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:subscription:uninstall") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully retrieved device details.", + response = List.class, + responseContainer = "List"), + @ApiResponse( + code = 404, + message = "Not Found. \n No Devices found which has application " + + "release of UUID.", + response = ErrorResponse.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n Found invalid payload with the request.", + response = List.class), + @ApiResponse( + code = 403, + message = "Forbidden. \n Don't have permission to get the details.", + response = List.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while getting data", + response = ErrorResponse.class) + }) + Response getAppInstalledDevicesOnCategories( + @ApiParam( + name="uuid", + value="uuid of the application release.", + required = true) + @PathParam("uuid") String uuid, + @ApiParam( + name="subType", + value="Subscription type of the application release.", + required = true) + @PathParam("subType") String subType, + @ApiParam( + name="subTypeName", + value="Subscription type name of the application release.", + required = true) + @PathParam("subTypeName") String subTypeName, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many device details you require from the starting " + + "pagination index/offset.", + defaultValue = "5") + @QueryParam("limit") int limit, + @ApiParam( + name = "name", + value = "The device name. For example, Nexus devices can have names, such as shamu, bullhead or angler.", + required = false) + @Size(max = 45) + String name, + @ApiParam( + name = "user", + value = "The username of the owner of the device.", + required = false) + @QueryParam("user") + String user, + @ApiParam( + name = "ownership", + allowableValues = "BYOD, COPE", + value = "Provide the ownership status of the device. The following values can be assigned:\n" + + "- BYOD: Bring Your Own Device\n" + + "- COPE: Corporate-Owned, Personally-Enabled", + required = false) + @QueryParam("ownership") + @Size(max = 45) + String ownership, + @ApiParam( + name = "status", + value = "Provide the device status details, such as active or inactive.") + @QueryParam("status") List status + ); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java index acf9662cb99..a6324c8fdb6 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.store.api/src/main/java/org/wso2/carbon/device/application/mgt/store/api/services/impl/SubscriptionManagementAPIImpl.java @@ -400,4 +400,73 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + @GET + @Consumes("application/json") + @Produces("application/json") + @Path("/{uuid}/{subType}/{subTypeName}/devices") + public Response getAppInstalledDevicesOnCategories( + @PathParam("uuid") String uuid, + @PathParam("subType") String subType, + @PathParam("subTypeName") String subTypeName, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit, + @QueryParam("name") String name, + @QueryParam("user") String user, + @QueryParam("ownership") String ownership, + @QueryParam("status") List status) { + try { + SubscriptionManager subscriptionManager = APIUtil.getSubscriptionManager(); + PaginationRequest request = new PaginationRequest(offset, limit); + + if (StringUtils.isNotBlank(name)) { + request.setDeviceName(name); + } + if (StringUtils.isNotBlank(user)) { + request.setOwner(user); + } + if (StringUtils.isNotBlank(ownership)) { + RequestValidationUtil.validateOwnershipType(ownership); + request.setOwnership(ownership); + } + if (status != null && !status.isEmpty()) { + boolean isStatusEmpty = true; + for (String statusString : status) { + if (StringUtils.isNotBlank(statusString)) { + isStatusEmpty = false; + break; + } + } + if (!isStatusEmpty) { + RequestValidationUtil.validateStatus(status); + request.setStatusList(status); + } + } + + //todo need to update the API for other subscription types + if (SubscriptionType.GROUP.toString().equalsIgnoreCase(subType)) { + PaginationResult subscribedCategoryDetails = subscriptionManager + .getAppInstalledSubscribeDevices(request, uuid, subType, subTypeName); + DeviceList devices = new DeviceList(); + devices.setList((List) subscribedCategoryDetails.getData()); + devices.setCount(subscribedCategoryDetails.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(devices).build(); + } else { + String msg = "Found invalid sub type: " + subType; + log.error(msg); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } + } catch (NotFoundException e) { + String msg = "Application with application release UUID: " + uuid + " is not found"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while getting application with the application " + + "release uuid: " + uuid; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index 77b9d76c5c4..9796dd40f49 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -758,4 +758,27 @@ public interface DeviceDAO { String version) throws DeviceManagementDAOException; int getFunctioningDevicesInSystem() throws DeviceManagementDAOException; + + /** + * This method is used to get the details of devices when give deviceIDs list and group name. + * @param deviceIds device ids of the devices. + * @param tenantId Id of the current tenant. + * @param request paginated request object. + * @param groupName group name. + * @return devices - device details list + * @throws DeviceManagementDAOException if connections establishment fails. + */ + List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException; + + /** + * @param deviceIds device ids of the devices. + * @param tenantId tenant id + * @param request paginated request object. + * @param groupName group name. + * @return number of device count under the group name. + * @throws DeviceManagementDAOException if error occurred while processing the SQL statement. + */ + int getGroupedDevicesCount(PaginationRequest request, List deviceIds, String groupName, int tenantId) + throws DeviceManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index bf387744e2f..dd175d493a9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -3022,4 +3022,154 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { throw new DeviceManagementDAOException(msg, e); } } + + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + List status = request.getStatusList(); + String name = request.getDeviceName(); + String user = request.getOwner(); + String ownership = request.getOwnership(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + if (StringUtils.isNotBlank(name)) { + query += " AND DM_DEVICE.NAME LIKE ?"; + } + if (StringUtils.isNotBlank(user)) { + query += " AND e.OWNER = ?"; + } + if (StringUtils.isNotBlank(ownership)) { + query += " AND e.OWNERSHIP = ?"; + } + if (status != null && !status.isEmpty()) { + query += buildStatusQuery(status); + } + + query += "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + if (StringUtils.isNotBlank(name)) { + ps.setString(index++, name); + } + if (StringUtils.isNotBlank(user)) { + ps.setString(index++, user); + } + if (StringUtils.isNotBlank(ownership)) { + ps.setString(index++, ownership); + } + if (status != null && !status.isEmpty()) { + for (String deviceStatus : status) { + ps.setString(index++, deviceStatus); + } + } + ps.setInt(index++, limitValue); + ps.setInt(index, offsetValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getGroupedDevicesCount(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + if (deviceIds.isEmpty()) { + return 0; + } + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "COUNT(DM_DEVICE_GROUP_MAP.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "WHERE DM_DEVICE_GROUP_MAP.DEVICE_ID IN (", + ") AND DM_GROUP.TENANT_ID = ?"); + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index, groupName); + } + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getInt("DEVICE_COUNT"); + } + return 0; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index 4393a4546e5..f2a91cae452 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -1194,6 +1194,79 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + query += " ORDER BY DEVICE_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + ps.setInt(index++, offsetValue); + ps.setInt(index, limitValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 8911beca49c..ae4b25b4315 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.device.mgt.core.dao.impl.device; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; @@ -1132,6 +1133,79 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getGroupedDevicesDetails(PaginationRequest request, List deviceIds, String groupName, + int tenantId) throws DeviceManagementDAOException { + int limitValue = request.getRowCount(); + int offsetValue = request.getStartIndex(); + try { + List devices = new ArrayList<>(); + if (deviceIds.isEmpty()) { + return devices; + } + Connection conn = this.getConnection(); + int index = 1; + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "DM_DEVICE.ID AS DEVICE_ID, " + + "DM_DEVICE.NAME AS DEVICE_NAME, " + + "DM_DEVICE.DESCRIPTION AS DESCRIPTION, " + + "DM_DEVICE.DEVICE_TYPE_ID, " + + "DM_DEVICE.DEVICE_IDENTIFICATION AS DEVICE_IDENTIFICATION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.DATE_OF_ENROLMENT, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.STATUS, " + + "e.IS_TRANSFERRED, " + + "device_types.NAME AS DEVICE_TYPE " + + "FROM DM_DEVICE_GROUP_MAP " + + "INNER JOIN DM_DEVICE ON " + + "DM_DEVICE_GROUP_MAP.DEVICE_ID = DM_DEVICE.ID " + + "INNER JOIN DM_GROUP ON " + + "DM_DEVICE_GROUP_MAP.GROUP_ID = DM_GROUP.ID " + + "INNER JOIN DM_ENROLMENT e ON " + + "DM_DEVICE.ID = e.DEVICE_ID AND " + + "DM_DEVICE.TENANT_ID = e.TENANT_ID " + + "INNER JOIN (SELECT ID, NAME FROM DM_DEVICE_TYPE) AS device_types ON " + + "device_types.ID = DM_DEVICE.DEVICE_TYPE_ID " + + "WHERE DM_DEVICE.ID IN (", + ") AND DM_DEVICE.TENANT_ID = ?"); + + deviceIds.stream().map(ignored -> "?").forEach(joiner::add); + String query = joiner.toString(); + if (StringUtils.isNotBlank(groupName)) { + query += " AND DM_GROUP.GROUP_NAME = ?"; + } + query += " ORDER BY DEVICE_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (Integer deviceId : deviceIds) { + ps.setInt(index++, deviceId); + } + ps.setInt(index++, tenantId); + if (StringUtils.isNotBlank(groupName)) { + ps.setString(index++, groupName); + } + ps.setInt(index++, offsetValue); + ps.setInt(index, limitValue); + + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + devices.add(DeviceManagementDAOUtil.loadDevice(rs)); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of all registered devices " + + "according to device ids and the limit area."; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + //TODO: Override for MSSQL /* @Override diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index 6ff661568c3..6265384aad9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -992,4 +992,14 @@ public interface DeviceManagementProviderService { License getLicenseConfig (String deviceTypeName) throws DeviceManagementException; + /** + * This method retrieves a list of devices details. + * @param request paginated request object. + * @param devicesIds devices ids list + * @param groupName name of the group + * @return {@link PaginationResult} + * @throws DeviceManagementException if any service level or DAO level error occurs. + */ + PaginationResult getDevicesDetails(PaginationRequest request, List devicesIds, String groupName) + throws DeviceManagementException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 1f4bac57d14..70cbee4731a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -4429,4 +4429,39 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return deviceManagementService.getLicenseConfig(); } + @Override + public PaginationResult getDevicesDetails(PaginationRequest request, List devicesIds, + String groupName) throws DeviceManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (log.isDebugEnabled()) { + log.debug("Getting all devices details for device ids: " + devicesIds); + } + PaginationResult paginationResult = new PaginationResult(); + List subscribedDeviceDetails; + try { + DeviceManagementDAOFactory.openConnection(); + subscribedDeviceDetails = deviceDAO.getGroupedDevicesDetails(request, devicesIds, groupName, tenantId); + if (subscribedDeviceDetails.isEmpty()) { + paginationResult.setData(new ArrayList<>()); + paginationResult.setRecordsFiltered(0); + paginationResult.setRecordsTotal(0); + return paginationResult; + } + int count = deviceDAO.getGroupedDevicesCount(request, devicesIds, groupName, tenantId); + paginationResult.setRecordsFiltered(count); + paginationResult.setRecordsTotal(count); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving device list for device ids " + devicesIds; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + paginationResult.setData(populateAllDeviceInfo(subscribedDeviceDetails)); + return paginationResult; + } }