Merge pull request #1102 from ViktorBasanets/entity-view
Entity view next
This commit is contained in:
		
						commit
						b0321157e0
					
				@ -318,7 +318,7 @@ public abstract class BaseController {
 | 
			
		||||
                    checkUserId(new UserId(entityId.getId()));
 | 
			
		||||
                    return;
 | 
			
		||||
                case ENTITY_VIEW:
 | 
			
		||||
                    checkEntityView(entityViewService.findEntityViewById(new EntityViewId(entityId.getId())));
 | 
			
		||||
                    checkEntityViewId(entityViewService.findEntityViewById(new EntityViewId(entityId.getId())));
 | 
			
		||||
                    return;
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType());
 | 
			
		||||
@ -351,14 +351,14 @@ public abstract class BaseController {
 | 
			
		||||
        try {
 | 
			
		||||
            validateId(entityViewId, "Incorrect entityViewId " + entityViewId);
 | 
			
		||||
            EntityView entityView = entityViewService.findEntityViewById(entityViewId);
 | 
			
		||||
            checkEntityView(entityView);
 | 
			
		||||
            checkEntityViewId(entityView);
 | 
			
		||||
            return entityView;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkEntityView(EntityView entityView) throws ThingsboardException {
 | 
			
		||||
    protected void checkEntityViewId(EntityView entityView) throws ThingsboardException {
 | 
			
		||||
        checkNotNull(entityView);
 | 
			
		||||
        checkTenantId(entityView.getTenantId());
 | 
			
		||||
        if (entityView.getCustomerId() != null && !entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,14 @@ package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.web.bind.annotation.PathVariable;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMethod;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestParam;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseStatus;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.thingsboard.server.common.data.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
@ -49,13 +56,10 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId)
 | 
			
		||||
            throws ThingsboardException {
 | 
			
		||||
 | 
			
		||||
    public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
 | 
			
		||||
        checkParameter(ENTITY_VIEW_ID, strEntityViewId);
 | 
			
		||||
        try {
 | 
			
		||||
            EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
 | 
			
		||||
            return checkEntityViewId(entityViewId);
 | 
			
		||||
            return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
@ -70,13 +74,10 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
            EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView));
 | 
			
		||||
            logEntityAction(savedEntityView.getId(), savedEntityView, null,
 | 
			
		||||
                    entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
 | 
			
		||||
 | 
			
		||||
            return savedEntityView;
 | 
			
		||||
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null,
 | 
			
		||||
                    entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
 | 
			
		||||
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -90,7 +91,6 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
            EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
 | 
			
		||||
            EntityView entityView = checkEntityViewId(entityViewId);
 | 
			
		||||
            entityViewService.deleteEntityView(entityViewId);
 | 
			
		||||
 | 
			
		||||
            logEntityAction(entityViewId, entityView, entityView.getCustomerId(),
 | 
			
		||||
                    ActionType.DELETED,null, strEntityViewId);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
@ -117,11 +117,9 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
            checkEntityViewId(entityViewId);
 | 
			
		||||
 | 
			
		||||
            EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(entityViewId, customerId));
 | 
			
		||||
 | 
			
		||||
            logEntityAction(entityViewId, savedEntityView,
 | 
			
		||||
                    savedEntityView.getCustomerId(),
 | 
			
		||||
                    ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName());
 | 
			
		||||
 | 
			
		||||
            return savedEntityView;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
 | 
			
		||||
@ -143,9 +141,7 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
                throw new IncorrectParameterException("Entity View isn't assigned to any customer!");
 | 
			
		||||
            }
 | 
			
		||||
            Customer customer = checkCustomerId(entityView.getCustomerId());
 | 
			
		||||
 | 
			
		||||
            EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(entityViewId));
 | 
			
		||||
 | 
			
		||||
            logEntityAction(entityViewId, entityView,
 | 
			
		||||
                    entityView.getCustomerId(),
 | 
			
		||||
                    ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName());
 | 
			
		||||
@ -208,7 +204,7 @@ public class EntityViewController extends BaseController {
 | 
			
		||||
            List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get());
 | 
			
		||||
            entityViews = entityViews.stream().filter(entityView -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    checkEntityView(entityView);
 | 
			
		||||
                    checkEntityViewId(entityView);
 | 
			
		||||
                    return true;
 | 
			
		||||
                } catch (ThingsboardException e) {
 | 
			
		||||
                    return false;
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,7 @@ import java.util.Set;
 | 
			
		||||
import static org.hamcrest.Matchers.containsString;
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertNotNull;
 | 
			
		||||
import static org.junit.Assert.assertNull;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
 | 
			
		||||
@ -319,12 +320,55 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTheCopyOfAttrsThatMatchWithDeviceCriteriaForTheView() throws Exception {
 | 
			
		||||
    public void testTheCopyOfAttrsIntoTSForTheView() throws Exception {
 | 
			
		||||
        Set<String> actualAttributesSet =
 | 
			
		||||
                getAttributesByKeys("{\"caValue1\":\"value1\", \"caValue2\":true, \"caValue3\":42.0, \"caValue4\":73}");
 | 
			
		||||
 | 
			
		||||
        Set<String> expectedActualAttributesSet =
 | 
			
		||||
                new HashSet<>(Arrays.asList("caValue1", "caValue2", "caValue3", "caValue4"));
 | 
			
		||||
        assertTrue(actualAttributesSet.containsAll(expectedActualAttributesSet));
 | 
			
		||||
        Thread.sleep(1000);
 | 
			
		||||
 | 
			
		||||
        EntityView savedView = getNewSavedEntityView("Test entity view");
 | 
			
		||||
        List<Map<String, Object>> values = doGetAsync("/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() +
 | 
			
		||||
                "/values/attributes?keys=" + String.join(",", actualAttributesSet), List.class);
 | 
			
		||||
 | 
			
		||||
        assertEquals("value1", getValue(values, "caValue1"));
 | 
			
		||||
        assertEquals(true, getValue(values, "caValue2"));
 | 
			
		||||
        assertEquals(42.0, getValue(values, "caValue3"));
 | 
			
		||||
        assertEquals(73, getValue(values, "caValue4"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTheCopyOfAttrsOutOfTSForTheView() throws Exception {
 | 
			
		||||
        Set<String> actualAttributesSet =
 | 
			
		||||
                getAttributesByKeys("{\"caValue1\":\"value1\", \"caValue2\":true, \"caValue3\":42.0, \"caValue4\":73}");
 | 
			
		||||
 | 
			
		||||
        Set<String> expectedActualAttributesSet = new HashSet<>(Arrays.asList("caValue1", "caValue2", "caValue3", "caValue4"));
 | 
			
		||||
        assertTrue(actualAttributesSet.containsAll(expectedActualAttributesSet));
 | 
			
		||||
        Thread.sleep(1000);
 | 
			
		||||
 | 
			
		||||
        List<Map<String, Object>> valueTelemetryOfDevices = doGetAsync("/api/plugins/telemetry/DEVICE/" + testDevice.getId().getId().toString() +
 | 
			
		||||
                "/values/attributes?keys=" + String.join(",", actualAttributesSet), List.class);
 | 
			
		||||
 | 
			
		||||
        EntityView view = new EntityView();
 | 
			
		||||
        view.setEntityId(testDevice.getId());
 | 
			
		||||
        view.setTenantId(savedTenant.getId());
 | 
			
		||||
        view.setName("Test entity view");
 | 
			
		||||
        view.setKeys(telemetry);
 | 
			
		||||
        view.setStartTimeMs((long) getValue(valueTelemetryOfDevices, "lastActivityTime") * 10);
 | 
			
		||||
        view.setEndTimeMs((long) getValue(valueTelemetryOfDevices, "lastActivityTime") / 10);
 | 
			
		||||
        EntityView savedView = doPost("/api/entityView", view, EntityView.class);
 | 
			
		||||
 | 
			
		||||
        List<Map<String, Object>> values = doGetAsync("/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() +
 | 
			
		||||
                "/values/attributes?keys=" + String.join(",", actualAttributesSet), List.class);
 | 
			
		||||
        assertEquals(0, values.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Set<String> getAttributesByKeys(String stringKV) throws Exception {
 | 
			
		||||
        String viewDeviceId = testDevice.getId().getId().toString();
 | 
			
		||||
        DeviceCredentials deviceCredentials
 | 
			
		||||
                = doGet("/api/device/" + viewDeviceId + "/credentials", DeviceCredentials.class);
 | 
			
		||||
 | 
			
		||||
        DeviceCredentials deviceCredentials =
 | 
			
		||||
                doGet("/api/device/" + viewDeviceId + "/credentials", DeviceCredentials.class);
 | 
			
		||||
        assertEquals(testDevice.getId(), deviceCredentials.getDeviceId());
 | 
			
		||||
 | 
			
		||||
        String accessToken = deviceCredentials.getCredentialsId();
 | 
			
		||||
@ -339,34 +383,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
 | 
			
		||||
        Thread.sleep(3000);
 | 
			
		||||
 | 
			
		||||
        MqttMessage message = new MqttMessage();
 | 
			
		||||
        message.setPayload(("{\"caValue1\":\"value1\", \"caValue2\":true, \"caValue3\":42.0, \"caValue4\":73}").getBytes());
 | 
			
		||||
        message.setPayload((stringKV).getBytes());
 | 
			
		||||
        client.publish("v1/devices/me/attributes", message);
 | 
			
		||||
        Thread.sleep(1000);
 | 
			
		||||
 | 
			
		||||
        List<String> actualTelemetry =
 | 
			
		||||
                doGetAsync("/api/plugins/telemetry/DEVICE/" + viewDeviceId +  "/keys/attributes", List.class);
 | 
			
		||||
        Set<String> actualTelemetrySet = new HashSet<>(actualTelemetry);
 | 
			
		||||
 | 
			
		||||
        List<String> expectedActualTelemetry = Arrays.asList("caValue1", "caValue2", "caValue3", "caValue4");
 | 
			
		||||
        Set<String> expectedActualTelemetrySet = new HashSet<>(expectedActualTelemetry);
 | 
			
		||||
        assertTrue(actualTelemetrySet.containsAll(expectedActualTelemetrySet));
 | 
			
		||||
        Thread.sleep(1000);
 | 
			
		||||
 | 
			
		||||
        EntityView savedView = getNewSavedEntityView("Test entity view");
 | 
			
		||||
        String urlOfTelemetryValues = "/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() +
 | 
			
		||||
                "/values/attributes?keys=" + String.join(",", actualTelemetrySet);
 | 
			
		||||
        List<Map<String, Object>> values = doGetAsync(urlOfTelemetryValues, List.class);
 | 
			
		||||
 | 
			
		||||
        assertEquals("value1", getValueOfMap(values, "caValue1"));
 | 
			
		||||
        assertEquals(true, getValueOfMap(values, "caValue2"));
 | 
			
		||||
        assertEquals(42.0, getValueOfMap(values, "caValue3"));
 | 
			
		||||
        assertEquals(73, getValueOfMap(values, "caValue4"));
 | 
			
		||||
        return new HashSet<>(doGetAsync("/api/plugins/telemetry/DEVICE/" + viewDeviceId +  "/keys/attributes", List.class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Object getValueOfMap(List<Map<String, Object>> values, String stringValue) {
 | 
			
		||||
        return values.stream()
 | 
			
		||||
                .filter(value -> value.get("key").equals(stringValue))
 | 
			
		||||
                .findFirst().get().get("value");
 | 
			
		||||
    private Object getValue(List<Map<String, Object>> values, String stringValue) {
 | 
			
		||||
        return values.size() == 0 ? null :
 | 
			
		||||
                values.stream()
 | 
			
		||||
                        .filter(value -> value.get("key").equals(stringValue))
 | 
			
		||||
                        .findFirst().get().get("value");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private EntityView getNewSavedEntityView(String name) throws Exception {
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
@RunWith(ClasspathSuite.class)
 | 
			
		||||
@ClasspathSuite.ClassnameFilters({
 | 
			
		||||
        "org.thingsboard.server.controller.sql.*Test",
 | 
			
		||||
        "org.thingsboard.server.controller.sql.EntityViewControllerSqlTest",
 | 
			
		||||
        })
 | 
			
		||||
public class ControllerSqlTestSuite {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
    public List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
        log.debug("Try to find entity views by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
 | 
			
		||||
        List<EntityViewEntity> entityViewEntities =
 | 
			
		||||
                findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ public interface EntityViewDao extends Dao<EntityView> {
 | 
			
		||||
     * @param pageLink the page link
 | 
			
		||||
     * @return the list of entity view objects
 | 
			
		||||
     */
 | 
			
		||||
    List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink);
 | 
			
		||||
    List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Find entity views by tenantId and entity view name.
 | 
			
		||||
 | 
			
		||||
@ -32,28 +32,27 @@ import java.util.List;
 | 
			
		||||
 */
 | 
			
		||||
public interface EntityViewService {
 | 
			
		||||
 | 
			
		||||
    EntityView findEntityViewById(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    EntityView saveEntityView(EntityView entityView);
 | 
			
		||||
 | 
			
		||||
    EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId);
 | 
			
		||||
 | 
			
		||||
    EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    void deleteEntityView(EntityViewId entityViewId);
 | 
			
		||||
    void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
 | 
			
		||||
 | 
			
		||||
    EntityView findEntityViewById(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    void deleteEntityViewsByTenantId(TenantId tenantId);
 | 
			
		||||
 | 
			
		||||
    TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId,
 | 
			
		||||
                                                                    TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
 | 
			
		||||
    TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId);
 | 
			
		||||
 | 
			
		||||
    void deleteEntityView(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    void deleteEntityViewsByTenantId(TenantId tenantId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.dao.entityview;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import com.google.common.util.concurrent.Futures;
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@ -25,6 +24,7 @@ import org.springframework.cache.Cache;
 | 
			
		||||
import org.springframework.cache.CacheManager;
 | 
			
		||||
import org.springframework.cache.annotation.CacheEvict;
 | 
			
		||||
import org.springframework.cache.annotation.Cacheable;
 | 
			
		||||
import org.springframework.cache.annotation.Caching;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.thingsboard.server.common.data.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.DataConstants;
 | 
			
		||||
@ -49,18 +49,17 @@ import org.thingsboard.server.dao.service.DataValidator;
 | 
			
		||||
import org.thingsboard.server.dao.service.PaginatedRemover;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantDao;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.concurrent.ExecutionException;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.common.data.CacheConstants.ENTITY_VIEW_CACHE;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateId;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateString;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by Victor Basanets on 8/28/2017.
 | 
			
		||||
@ -89,62 +88,32 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private CacheManager cacheManager;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityView findEntityViewById(EntityViewId entityViewId) {
 | 
			
		||||
        log.trace("Executing findEntityViewById [{}]", entityViewId);
 | 
			
		||||
        validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
 | 
			
		||||
        return entityViewDao.findById(entityViewId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.tenantId, #entityView.name}")
 | 
			
		||||
    @Caching(evict = {
 | 
			
		||||
            @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.tenantId, #entityView.entityId}"),
 | 
			
		||||
            @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.id}")})
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityView saveEntityView(EntityView entityView) {
 | 
			
		||||
        log.trace("Executing save entity view [{}]", entityView);
 | 
			
		||||
        entityViewValidator.validate(entityView);
 | 
			
		||||
        EntityView savedEntityView = entityViewDao.save(entityView);
 | 
			
		||||
 | 
			
		||||
        List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
 | 
			
		||||
        if (savedEntityView.getKeys() != null) {
 | 
			
		||||
            copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs());
 | 
			
		||||
            copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs());
 | 
			
		||||
            copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh());
 | 
			
		||||
            futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs()));
 | 
			
		||||
            futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs()));
 | 
			
		||||
            futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh()));
 | 
			
		||||
        }
 | 
			
		||||
        for (ListenableFuture<List<Void>> future : futures) {
 | 
			
		||||
            try {
 | 
			
		||||
                future.get();
 | 
			
		||||
            } catch (InterruptedException | ExecutionException e) {
 | 
			
		||||
                log.error("Failed to copy attributes to entity view", e);
 | 
			
		||||
                throw new RuntimeException("Failed to copy attributes to entity view", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return savedEntityView;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys) {
 | 
			
		||||
        if (keys != null && !keys.isEmpty()) {
 | 
			
		||||
            ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
 | 
			
		||||
            Futures.addCallback(getAttrFuture, new FutureCallback<List<AttributeKvEntry>>() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onSuccess(@Nullable List<AttributeKvEntry> attributeKvEntries) {
 | 
			
		||||
                    if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
 | 
			
		||||
                        List<AttributeKvEntry> filteredAttributes =
 | 
			
		||||
                                attributeKvEntries.stream()
 | 
			
		||||
                                        .filter(attributeKvEntry -> {
 | 
			
		||||
                                            if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() == 0) {
 | 
			
		||||
                                                return true;
 | 
			
		||||
                                            }
 | 
			
		||||
                                            if (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs()) {
 | 
			
		||||
                                                return true;
 | 
			
		||||
                                            }
 | 
			
		||||
                                            if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs()) {
 | 
			
		||||
                                                return true;
 | 
			
		||||
                                            }
 | 
			
		||||
                                            return entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs()
 | 
			
		||||
                                                    && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs();
 | 
			
		||||
                                        }).collect(Collectors.toList());
 | 
			
		||||
                        attributesService.save(entityView.getId(), scope, filteredAttributes);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onFailure(Throwable throwable) {
 | 
			
		||||
                    log.error("Failed to fetch [{}] attributes [{}] for [{}] entity [{}]",
 | 
			
		||||
                            scope, keys, entityView.getEntityId().getEntityType().name(), entityView.getEntityId().getId().toString(), throwable);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId) {
 | 
			
		||||
        EntityView entityView = findEntityViewById(entityViewId);
 | 
			
		||||
@ -152,6 +121,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
        return saveEntityView(entityView);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId) {
 | 
			
		||||
        EntityView entityView = findEntityViewById(entityViewId);
 | 
			
		||||
@ -159,49 +129,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
        return saveEntityView(entityView);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteEntityView(EntityViewId entityViewId) {
 | 
			
		||||
        log.trace("Executing deleteEntityView [{}]", entityViewId);
 | 
			
		||||
        Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE);
 | 
			
		||||
        validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
 | 
			
		||||
        deleteEntityRelations(entityViewId);
 | 
			
		||||
        EntityView entityView = entityViewDao.findById(entityViewId.getId());
 | 
			
		||||
        cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getName()));
 | 
			
		||||
        entityViewDao.removeById(entityViewId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink) {
 | 
			
		||||
        log.trace("Executing findEntityViewByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
 | 
			
		||||
        List<EntityView> entityViews = entityViewDao.findEntityViewByTenantId(tenantId.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(entityViews, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteEntityViewsByTenantId(TenantId tenantId) {
 | 
			
		||||
        log.trace("Executing deleteEntityViewsByTenantId, tenantId [{}]", tenantId);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        tenantEntityViewRemover.removeEntities(tenantId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId,
 | 
			
		||||
                                                                          TextPageLink pageLink) {
 | 
			
		||||
 | 
			
		||||
        log.trace("Executing findEntityViewByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," +
 | 
			
		||||
                        " pageLink [{}]", tenantId, customerId, pageLink);
 | 
			
		||||
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
 | 
			
		||||
        validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
 | 
			
		||||
        List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(),
 | 
			
		||||
                customerId.getId(), pageLink);
 | 
			
		||||
 | 
			
		||||
        return new TextPageData<>(entityViews, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId) {
 | 
			
		||||
        log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId);
 | 
			
		||||
@ -210,11 +137,34 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
        new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
 | 
			
		||||
    public EntityView findEntityViewById(EntityViewId entityViewId) {
 | 
			
		||||
        log.trace("Executing findEntityViewById [{}]", entityViewId);
 | 
			
		||||
        validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
 | 
			
		||||
        return entityViewDao.findByIdAsync(entityViewId.getId());
 | 
			
		||||
        return entityViewDao.findById(entityViewId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink) {
 | 
			
		||||
        log.trace("Executing findEntityViewsByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
 | 
			
		||||
        List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantId(tenantId.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(entityViews, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId,
 | 
			
		||||
                                                                           TextPageLink pageLink) {
 | 
			
		||||
        log.trace("Executing findEntityViewByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," +
 | 
			
		||||
                " pageLink [{}]", tenantId, customerId, pageLink);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
 | 
			
		||||
        validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink);
 | 
			
		||||
        List<EntityView> entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(),
 | 
			
		||||
                customerId.getId(), pageLink);
 | 
			
		||||
        return new TextPageData<>(entityViews, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -231,10 +181,17 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
            }
 | 
			
		||||
            return Futures.successfulAsList(futures);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return entityViews;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
 | 
			
		||||
        log.trace("Executing findEntityViewById [{}]", entityViewId);
 | 
			
		||||
        validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
 | 
			
		||||
        return entityViewDao.findByIdAsync(entityViewId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Cacheable(cacheNames = ENTITY_VIEW_CACHE, key = "{#tenantId, #entityId}")
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        log.trace("Executing findEntityViewsByTenantIdAndEntityIdAsync, tenantId [{}], entityId [{}]", tenantId, entityId);
 | 
			
		||||
@ -243,13 +200,62 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
        return entityViewDao.findEntityViewsByTenantIdAndEntityIdAsync(tenantId.getId(), entityId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}")
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteEntityView(EntityViewId entityViewId) {
 | 
			
		||||
        log.trace("Executing deleteEntityView [{}]", entityViewId);
 | 
			
		||||
        validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
 | 
			
		||||
        deleteEntityRelations(entityViewId);
 | 
			
		||||
        Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE);
 | 
			
		||||
        EntityView entityView = entityViewDao.findById(entityViewId.getId());
 | 
			
		||||
        cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getEntityId()));
 | 
			
		||||
        entityViewDao.removeById(entityViewId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteEntityViewsByTenantId(TenantId tenantId) {
 | 
			
		||||
        log.trace("Executing deleteEntityViewsByTenantId, tenantId [{}]", tenantId);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        tenantEntityViewRemover.removeEntities(tenantId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys) {
 | 
			
		||||
        if (keys != null && !keys.isEmpty()) {
 | 
			
		||||
            ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
 | 
			
		||||
            return Futures.transform(getAttrFuture, attributeKvEntries -> {
 | 
			
		||||
                List<AttributeKvEntry> filteredAttributes = new ArrayList<>();
 | 
			
		||||
                if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
 | 
			
		||||
                    filteredAttributes =
 | 
			
		||||
                            attributeKvEntries.stream()
 | 
			
		||||
                                    .filter(attributeKvEntry -> {
 | 
			
		||||
                                        long startTime = entityView.getStartTimeMs();
 | 
			
		||||
                                        long endTime = entityView.getEndTimeMs();
 | 
			
		||||
                                        long lastUpdateTs = attributeKvEntry.getLastUpdateTs();
 | 
			
		||||
                                        return startTime == 0 && endTime == 0 ||
 | 
			
		||||
                                                (endTime == 0 && startTime < lastUpdateTs) ||
 | 
			
		||||
                                                (startTime == 0 && endTime > lastUpdateTs)
 | 
			
		||||
                                                ? true : startTime < lastUpdateTs && endTime > lastUpdateTs;
 | 
			
		||||
                                    }).collect(Collectors.toList());
 | 
			
		||||
                }
 | 
			
		||||
                try {
 | 
			
		||||
                    return attributesService.save(entityView.getId(), scope, filteredAttributes).get();
 | 
			
		||||
                } catch (InterruptedException | ExecutionException e) {
 | 
			
		||||
                    log.error("Failed to copy attributes to entity view", e);
 | 
			
		||||
                    throw new RuntimeException("Failed to copy attributes to entity view", e);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            return Futures.immediateFuture(null);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private DataValidator<EntityView> entityViewValidator =
 | 
			
		||||
            new DataValidator<EntityView>() {
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                protected void validateCreate(EntityView entityView) {
 | 
			
		||||
                    entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName())
 | 
			
		||||
                            .ifPresent( e -> {
 | 
			
		||||
                            .ifPresent(e -> {
 | 
			
		||||
                                throw new DataValidationException("Entity view with such name already exists!");
 | 
			
		||||
                            });
 | 
			
		||||
                }
 | 
			
		||||
@ -257,7 +263,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
                @Override
 | 
			
		||||
                protected void validateUpdate(EntityView entityView) {
 | 
			
		||||
                    entityViewDao.findEntityViewByTenantIdAndName(entityView.getTenantId().getId(), entityView.getName())
 | 
			
		||||
                            .ifPresent( e -> {
 | 
			
		||||
                            .ifPresent(e -> {
 | 
			
		||||
                                if (!e.getUuidId().equals(entityView.getUuidId())) {
 | 
			
		||||
                                    throw new DataValidationException("Entity view with such name already exists!");
 | 
			
		||||
                                }
 | 
			
		||||
@ -296,7 +302,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                protected List<EntityView> findEntities(TenantId id, TextPageLink pageLink) {
 | 
			
		||||
                    return entityViewDao.findEntityViewByTenantId(id.getId(), pageLink);
 | 
			
		||||
                    return entityViewDao.findEntityViewsByTenantId(id.getId(), pageLink);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao<EntityViewEntity,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
    public List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) {
 | 
			
		||||
        return DaoUtil.convertDataList(
 | 
			
		||||
                entityViewRepository.findByTenantId(
 | 
			
		||||
                        fromTimeUUID(tenantId),
 | 
			
		||||
 | 
			
		||||
@ -15,9 +15,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.rule.engine.action;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import com.google.common.base.Function;
 | 
			
		||||
import com.google.common.util.concurrent.Futures;
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import com.google.gson.JsonParser;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@ -28,24 +26,23 @@ import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbRelationTypes;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.DonAsynchron;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.DataConstants;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 | 
			
		||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentType;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
import org.thingsboard.server.common.msg.session.SessionMsgType;
 | 
			
		||||
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ExecutionException;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback;
 | 
			
		||||
import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@RuleNode(
 | 
			
		||||
@ -70,25 +67,22 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException {
 | 
			
		||||
        if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
 | 
			
		||||
                msg.getType().equals(DataConstants.ATTRIBUTES_DELETED) ||
 | 
			
		||||
                msg.getType().equals(DataConstants.ATTRIBUTES_UPDATED)) {
 | 
			
		||||
        if (!msg.getMetaData().getData().isEmpty()) {
 | 
			
		||||
            long now = System.currentTimeMillis();
 | 
			
		||||
            String scope;
 | 
			
		||||
            if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name())) {
 | 
			
		||||
                scope = DataConstants.CLIENT_SCOPE;
 | 
			
		||||
            } else {
 | 
			
		||||
                scope = msg.getMetaData().getValue("scope");
 | 
			
		||||
            }
 | 
			
		||||
            String scope = msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ?
 | 
			
		||||
                    DataConstants.CLIENT_SCOPE : msg.getMetaData().getValue("scope");
 | 
			
		||||
 | 
			
		||||
            ListenableFuture<List<EntityView>> entityViewsFuture =
 | 
			
		||||
                    ctx.getEntityViewService().findEntityViewsByTenantIdAndEntityIdAsync(ctx.getTenantId(), msg.getOriginator());
 | 
			
		||||
            withCallback(entityViewsFuture,
 | 
			
		||||
 | 
			
		||||
            DonAsynchron.withCallback(entityViewsFuture,
 | 
			
		||||
                    entityViews -> {
 | 
			
		||||
                        List<ListenableFuture<List<Void>>> saveFutures = new ArrayList<>();
 | 
			
		||||
                        for (EntityView entityView : entityViews) {
 | 
			
		||||
                            if ((entityView.getEndTimeMs() != 0  && entityView.getEndTimeMs() > now && entityView.getStartTimeMs() < now) ||
 | 
			
		||||
                                    (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < now)) {
 | 
			
		||||
                                Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes();
 | 
			
		||||
                            long startTime = entityView.getStartTimeMs();
 | 
			
		||||
                            long endTime = entityView.getEndTimeMs();
 | 
			
		||||
                            if ((endTime != 0  && endTime > now && startTime < now) || (endTime == 0 && startTime < now)) {
 | 
			
		||||
                                Set<AttributeKvEntry> attributes =
 | 
			
		||||
                                        JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes();
 | 
			
		||||
                                List<AttributeKvEntry> filteredAttributes =
 | 
			
		||||
                                        attributes.stream()
 | 
			
		||||
                                                .filter(attr -> {
 | 
			
		||||
@ -110,19 +104,22 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
 | 
			
		||||
                                                            return entityView.getKeys().getAttributes().getSh().contains(attr.getKey());
 | 
			
		||||
                                                    }
 | 
			
		||||
                                                    return false;
 | 
			
		||||
                                                })
 | 
			
		||||
                                                .collect(Collectors.toList());
 | 
			
		||||
                                saveFutures.add(ctx.getAttributesService().save(entityView.getId(), scope, new ArrayList<>(filteredAttributes)));
 | 
			
		||||
                                                }).collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
                                ctx.getTelemetryService().saveAndNotify(entityView.getId(), scope, filteredAttributes,
 | 
			
		||||
                                        new FutureCallback<Void>() {
 | 
			
		||||
                                            @Override
 | 
			
		||||
                                            public void onSuccess(@Nullable Void result) {
 | 
			
		||||
                                                ctx.tellNext(msg, SUCCESS);
 | 
			
		||||
                                            }
 | 
			
		||||
 | 
			
		||||
                                            @Override
 | 
			
		||||
                                            public void onFailure(Throwable t) {
 | 
			
		||||
                                                ctx.tellFailure(msg, t);
 | 
			
		||||
                                            }
 | 
			
		||||
                                        });
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        Futures.transform(Futures.allAsList(saveFutures), new Function<List<List<Void>>, Object>() {
 | 
			
		||||
                            @Nullable
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public Object apply(@Nullable List<List<Void>> lists) {
 | 
			
		||||
                                ctx.tellNext(msg, TbRelationTypes.SUCCESS);
 | 
			
		||||
                                return null;
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
                    },
 | 
			
		||||
                    t -> ctx.tellFailure(msg, t));
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user