com.devicehive.service.DeviceClassService.java Source code

Java tutorial

Introduction

Here is the source code for com.devicehive.service.DeviceClassService.java

Source

package com.devicehive.service;

/*
 * #%L
 * DeviceHive Java Server Common business logic
 * %%
 * Copyright (C) 2016 DataArt
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.devicehive.configuration.Messages;
import com.devicehive.dao.DeviceClassDao;
import com.devicehive.exceptions.HiveException;
import com.devicehive.model.rpc.ListDeviceClassRequest;
import com.devicehive.model.rpc.ListDeviceClassResponse;
import com.devicehive.model.updates.DeviceClassUpdate;
import com.devicehive.model.updates.EquipmentUpdate;
import com.devicehive.service.helpers.ResponseConsumer;
import com.devicehive.shim.api.Request;
import com.devicehive.shim.api.client.RpcClient;
import com.devicehive.util.HiveValidator;
import com.devicehive.vo.DeviceClassEquipmentVO;
import com.devicehive.vo.DeviceClassWithEquipmentVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import javax.ws.rs.core.Response;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;

@Component
public class DeviceClassService {

    @Autowired
    private HiveValidator hiveValidator;
    @Autowired
    private DeviceClassDao deviceClassDao;
    @Autowired
    private RpcClient rpcClient;

    @Transactional
    public void delete(@NotNull long id) {
        deviceClassDao.remove(id);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public DeviceClassWithEquipmentVO getWithEquipment(@NotNull Long id) {
        return deviceClassDao.find(id);
    }

    @Transactional
    public DeviceClassWithEquipmentVO createOrUpdateDeviceClass(Optional<DeviceClassUpdate> deviceClass,
            Set<DeviceClassEquipmentVO> customEquipmentSet) {
        DeviceClassWithEquipmentVO stored;
        //use existing
        if (deviceClass == null || !deviceClass.isPresent()) {
            return null;
        }
        //check is already done
        DeviceClassUpdate deviceClassUpdate = deviceClass.orElse(null);
        DeviceClassWithEquipmentVO deviceClassFromMessage = deviceClassUpdate.convertTo();
        if (deviceClassFromMessage.getId() != null) {
            stored = deviceClassDao.find(deviceClassFromMessage.getId());
        } else {
            stored = deviceClassDao.findByName(deviceClassFromMessage.getName());
        }
        if (stored != null) {
            if (!stored.getIsPermanent()) {
                deviceClassUpdate.setEquipment(Optional.ofNullable(customEquipmentSet));
                update(stored.getId(), deviceClassUpdate);
            }
            return stored;
        } else {
            return addDeviceClass(deviceClassFromMessage);
        }
    }

    @Transactional
    public DeviceClassWithEquipmentVO addDeviceClass(DeviceClassWithEquipmentVO deviceClass) {
        if (deviceClassDao.findByName(deviceClass.getName()) != null) {
            throw new HiveException(Messages.DEVICE_CLASS_WITH_SUCH_NAME_AND_VERSION_EXISTS,
                    FORBIDDEN.getStatusCode());
        }
        if (deviceClass.getIsPermanent() == null) {
            deviceClass.setIsPermanent(false);
        }
        hiveValidator.validate(deviceClass);
        deviceClass = deviceClassDao.persist(deviceClass);
        // TODO [rafa] looks strange, very strange
        //        if (deviceClass.getEquipment() != null) {
        //            Set<Equipment> resultEquipment = createEquipment(deviceClass, deviceClass.getEquipment());
        //            deviceClass.setEquipment(resultEquipment);
        //        }
        return deviceClass;
    }

    @Transactional
    public DeviceClassWithEquipmentVO update(@NotNull Long id, DeviceClassUpdate update) {
        DeviceClassWithEquipmentVO stored = deviceClassDao.find(id);
        if (stored == null) {
            throw new HiveException(String.format(Messages.DEVICE_CLASS_NOT_FOUND, id),
                    Response.Status.NOT_FOUND.getStatusCode());
        }
        if (update == null) {
            return null;
        }
        if (update.getData() != null) {
            stored.setData(update.getData().orElse(null));
        }
        if (update.getEquipment() != null) {
            if (update.getEquipment().isPresent()) {
                Map<String, DeviceClassEquipmentVO> existing = new HashMap<>();
                for (DeviceClassEquipmentVO deviceClassEquipmentVO : stored.getEquipment()) {
                    existing.put(deviceClassEquipmentVO.getCode(), deviceClassEquipmentVO);
                }

                for (DeviceClassEquipmentVO deviceClassEquipmentVO : update.getEquipment().get()) {
                    if (existing.containsKey(deviceClassEquipmentVO.getCode())) {
                        Long existingEquipmentId = existing.get(deviceClassEquipmentVO.getCode()).getId();
                        deviceClassEquipmentVO.setId(existingEquipmentId);
                    }
                }
                stored.setEquipment(update.getEquipment().orElse(null));
            }
        }
        if (update.getId() != null) {
            stored.setId(update.getId());
        }
        if (update.getName() != null) {
            stored.setName(update.getName().orElse(null));
        }
        if (update.getPermanent() != null) {
            stored.setIsPermanent(update.getPermanent().orElse(null));
        }
        hiveValidator.validate(stored);
        return deviceClassDao.merge(stored);
    }

    /**
     * updates Equipment attributes
     *
     * @param equipmentUpdate Equipment instance, containing fields to update (Id field will be ignored)
     * @param equipmentId     id of equipment to update
     * @param deviceClassId   class of equipment to update
     * @return true, if update successful, false otherwise
     */
    @Transactional
    public boolean update(EquipmentUpdate equipmentUpdate, @NotNull long equipmentId, @NotNull long deviceClassId) {
        if (equipmentUpdate == null) {
            return true;
        }
        DeviceClassWithEquipmentVO stored = deviceClassDao.find(deviceClassId);
        DeviceClassEquipmentVO found = null;
        for (DeviceClassEquipmentVO deviceClassEquipmentVO : stored.getEquipment()) {
            if (deviceClassEquipmentVO.getId().equals(equipmentId)) {
                found = deviceClassEquipmentVO;
            }
        }

        if (found == null) {
            return false; // equipment with id = equipmentId does not exists
        }
        if (equipmentUpdate.getCode() != null) {
            found.setCode(equipmentUpdate.getCode().orElse(null));
        }
        if (equipmentUpdate.getName() != null) {
            found.setName(equipmentUpdate.getName().orElse(null));
        }
        if (equipmentUpdate.getType() != null) {
            found.setType(equipmentUpdate.getType().orElse(null));
        }
        if (equipmentUpdate.getData() != null) {
            found.setData(equipmentUpdate.getData().orElse(null));
        }
        deviceClassDao.merge(stored);
        return true;
    }

    @Transactional
    public Set<DeviceClassEquipmentVO> createEquipment(@NotNull Long classId,
            @NotNull Set<DeviceClassEquipmentVO> equipments) {
        DeviceClassWithEquipmentVO deviceClass = deviceClassDao.find(classId);
        Set<String> existingCodesSet = deviceClass.getEquipment().stream().map(DeviceClassEquipmentVO::getCode)
                .collect(Collectors.toSet());
        Set<String> newCodeSet = equipments.stream().map(DeviceClassEquipmentVO::getCode)
                .collect(Collectors.toSet());

        newCodeSet.retainAll(existingCodesSet);
        if (!newCodeSet.isEmpty()) {
            String codeSet = StringUtils.join(newCodeSet, ",");
            throw new HiveException(String.format(Messages.DUPLICATE_EQUIPMENT_ENTRY, codeSet, classId),
                    FORBIDDEN.getStatusCode());
        }

        deviceClass.getEquipment().addAll(equipments);

        deviceClass = deviceClassDao.merge(deviceClass);

        //TODO [rafa] duuumb, and lazy, in case of several equipments linked to the class two for loops is fine.
        for (DeviceClassEquipmentVO equipment : equipments) {
            for (DeviceClassEquipmentVO s : deviceClass.getEquipment()) {
                if (equipment.getCode().equals(s.getCode())) {
                    equipment.setId(s.getId());
                }
            }
        }

        return equipments;
    }

    @Transactional
    public DeviceClassEquipmentVO createEquipment(Long classId, DeviceClassEquipmentVO equipment) {
        DeviceClassWithEquipmentVO deviceClass = deviceClassDao.find(classId);
        if (deviceClass == null) {
            throw new HiveException(String.format(Messages.DEVICE_CLASS_NOT_FOUND, classId),
                    NOT_FOUND.getStatusCode());
        }
        if (deviceClass.getIsPermanent()) {
            throw new HiveException(Messages.UPDATE_PERMANENT_EQUIPMENT, NOT_FOUND.getStatusCode());
        }
        Set<DeviceClassEquipmentVO> equipments = deviceClass.getEquipment();
        String newCode = equipment.getCode();
        if (equipments != null) {
            for (DeviceClassEquipmentVO e : equipments) {
                if (newCode.equals(e.getCode())) {
                    String errorMessage = String.format(Messages.DUPLICATE_EQUIPMENT_ENTRY, e.getCode(), classId);
                    throw new HiveException(errorMessage, FORBIDDEN.getStatusCode());
                }
            }
        }

        deviceClass.getEquipment().add(equipment);
        deviceClass = deviceClassDao.merge(deviceClass);

        //TODO [rafa] find device equipment class back from the set in device class.
        for (DeviceClassEquipmentVO s : deviceClass.getEquipment()) {
            if (equipment.getCode().equals(s.getCode())) {
                equipment.setId(s.getId());
            }
        }

        return equipment;
    }

    //@Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CompletableFuture<List<DeviceClassWithEquipmentVO>> list(String name, String namePattern,
            String sortField, Boolean sortOrderAsc, Integer take, Integer skip) {
        ListDeviceClassRequest request = new ListDeviceClassRequest();
        request.setName(name);
        request.setNamePattern(namePattern);
        request.setSortField(sortField);
        request.setSortOrderAsc(sortOrderAsc);
        request.setTake(take);
        request.setSkip(skip);

        CompletableFuture<com.devicehive.shim.api.Response> future = new CompletableFuture<>();

        rpcClient.call(Request.newBuilder().withBody(request).build(), new ResponseConsumer(future));

        return future.thenApply(r -> ((ListDeviceClassResponse) r.getBody()).getDeviceClasses());
    }

    /**
     * Delete Equipment (not DeviceEquipment, but whole equipment with appropriate device Equipments)
     *
     * @param equipmentId   equipment id to delete
     * @param deviceClassId id of deviceClass which equipment belongs used to double check
     * @return true if deleted successfully
     */
    @Transactional
    public boolean delete(@NotNull long equipmentId, @NotNull long deviceClassId) {
        DeviceClassWithEquipmentVO stored = deviceClassDao.find(deviceClassId);
        DeviceClassEquipmentVO found = null;
        Iterator<DeviceClassEquipmentVO> iterator = stored.getEquipment().iterator();
        while (iterator.hasNext()) {
            DeviceClassEquipmentVO deviceClassEquipmentVO = iterator.next();
            if (deviceClassEquipmentVO.getId().equals(equipmentId)) {
                iterator.remove();
                found = deviceClassEquipmentVO;
            }
        }

        if (found != null) {
            deviceClassDao.merge(stored);
        }

        return found != null;
    }

    /**
     * Retrieves Equipment from database
     *
     * @param deviceClassId parent device class id for this equipment
     * @param equipmentId   id of equipment to get
     */
    @Transactional(readOnly = true)
    public DeviceClassEquipmentVO getByDeviceClass(@NotNull long deviceClassId, @NotNull long equipmentId) {
        return deviceClassDao.findDeviceClassEquipment(deviceClassId, equipmentId);
    }

    /**
     * Retrieves Equipment from database
     *
     * @param deviceClassId parent device class id for this equipment
     */
    @Transactional(readOnly = true)
    public Set<DeviceClassEquipmentVO> getByDeviceClass(@NotNull long deviceClassId) {
        return deviceClassDao.find(deviceClassId).getEquipment();
    }

}