thingsboard-aplcache

Fixed for entity view afte testing

10/16/2018 10:26:01 AM

Details

diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
index 889630b..154ed3a 100644
--- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
@@ -51,6 +51,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
 import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
 import org.thingsboard.server.dao.alarm.AlarmService;
 import org.thingsboard.server.dao.asset.AssetService;
+import org.thingsboard.server.dao.attributes.AttributesService;
 import org.thingsboard.server.dao.audit.AuditLogService;
 import org.thingsboard.server.dao.customer.CustomerService;
 import org.thingsboard.server.dao.dashboard.DashboardService;
@@ -70,6 +71,7 @@ import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
 import org.thingsboard.server.service.component.ComponentDiscoveryService;
 import org.thingsboard.server.service.security.model.SecurityUser;
 import org.thingsboard.server.service.state.DeviceStateService;
+import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
 
 import javax.mail.MessagingException;
 import javax.servlet.http.HttpServletRequest;
@@ -143,6 +145,12 @@ public abstract class BaseController {
     @Autowired
     protected EntityViewService entityViewService;
 
+    @Autowired
+    protected TelemetrySubscriptionService tsSubService;
+
+    @Autowired
+    protected AttributesService attributesService;
+
     @ExceptionHandler(ThingsboardException.class)
     public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
         errorResponseHandler.handle(ex, response);
diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
index a1ba1c6..69e28db 100644
--- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
@@ -15,7 +15,10 @@
  */
 package org.thingsboard.server.controller;
 
+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;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -26,7 +29,9 @@ 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.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
 import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.DataConstants;
 import org.thingsboard.server.common.data.EntitySubtype;
 import org.thingsboard.server.common.data.EntityType;
 import org.thingsboard.server.common.data.EntityView;
@@ -34,15 +39,24 @@ import org.thingsboard.server.common.data.audit.ActionType;
 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
 import org.thingsboard.server.common.data.exception.ThingsboardException;
 import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.EntityId;
 import org.thingsboard.server.common.data.id.EntityViewId;
 import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.id.UUIDBased;
+import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 import org.thingsboard.server.common.data.page.TextPageData;
 import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.msg.cluster.SendToClusterMsg;
 import org.thingsboard.server.dao.exception.IncorrectParameterException;
 import org.thingsboard.server.dao.model.ModelConstants;
 import org.thingsboard.server.service.security.model.SecurityUser;
 
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
 import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID;
@@ -52,6 +66,7 @@ import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID;
  */
 @RestController
 @RequestMapping("/api")
+@Slf4j
 public class EntityViewController extends BaseController {
 
     public static final String ENTITY_VIEW_ID = "entityViewId";
@@ -75,6 +90,20 @@ public class EntityViewController extends BaseController {
         try {
             entityView.setTenantId(getCurrentUser().getTenantId());
             EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView));
+            List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
+            if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
+                futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs(), getCurrentUser()));
+                futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs(), getCurrentUser()));
+                futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh(), getCurrentUser()));
+            }
+            for (ListenableFuture<List<Void>> future : futures) {
+                try {
+                    future.get();
+                } catch (InterruptedException | ExecutionException e) {
+                    throw new RuntimeException("Failed to copy attributes to entity view", e);
+                }
+            }
+
             logEntityAction(savedEntityView.getId(), savedEntityView, null,
                     entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
             return savedEntityView;
@@ -85,6 +114,62 @@ public class EntityViewController extends BaseController {
         }
     }
 
+    private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException {
+        EntityViewId entityId = entityView.getId();
+        if (keys != null && !keys.isEmpty()) {
+            ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
+            return Futures.transform(getAttrFuture, attributeKvEntries -> {
+                List<AttributeKvEntry> attributes;
+                if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
+                    attributes =
+                            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());
+                    tsSubService.saveAndNotify(entityId, scope, attributes, new FutureCallback<Void>() {
+                        @Override
+                        public void onSuccess(@Nullable Void tmp) {
+                            try {
+                                logAttributesUpdated(user, entityId, scope, attributes, null);
+                            } catch (ThingsboardException e) {
+                                log.error("Failed to log attribute updates", e);
+                            }
+                            if (entityId.getEntityType() == EntityType.ENTITY_VIEW) {
+                                DeviceId deviceId = new DeviceId(entityId.getId());
+                                DeviceAttributesEventNotificationMsg notificationMsg = DeviceAttributesEventNotificationMsg.onUpdate(
+                                        user.getTenantId(), deviceId, scope, attributes);
+                                actorService.onMsg(new SendToClusterMsg(deviceId, notificationMsg));
+                            }
+                        }
+
+                        @Override
+                        public void onFailure(Throwable t) {
+                            try {
+                                logAttributesUpdated(user, entityId, scope, attributes, t);
+                            } catch (ThingsboardException e) {
+                                log.error("Failed to log attribute updates", e);
+                            }
+                        }
+                    });
+                }
+                return null;
+            });
+        } else {
+            return Futures.immediateFuture(null);
+        }
+    }
+
+    private void logAttributesUpdated(SecurityUser user, EntityId entityId, String scope, List<AttributeKvEntry> attributes, Throwable e) throws ThingsboardException {
+        logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.ATTRIBUTES_UPDATED, toException(e),
+                scope, attributes);
+    }
+
     @PreAuthorize("hasAuthority('TENANT_ADMIN')")
     @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE)
     @ResponseStatus(value = HttpStatus.OK)
diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
index 7062ca9..9f92019 100644
--- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
@@ -94,15 +94,9 @@ import java.util.stream.Collectors;
 public class TelemetryController extends BaseController {
 
     @Autowired
-    private AttributesService attributesService;
-
-    @Autowired
     private TimeseriesService tsService;
 
     @Autowired
-    private TelemetrySubscriptionService tsSubService;
-
-    @Autowired
     private AccessValidator accessValidator;
 
     private ExecutorService executor;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
index 1b67ca0..33a2699 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
@@ -29,6 +29,7 @@ import org.thingsboard.server.dao.asset.AssetService;
 import org.thingsboard.server.dao.customer.CustomerService;
 import org.thingsboard.server.dao.dashboard.DashboardService;
 import org.thingsboard.server.dao.device.DeviceService;
+import org.thingsboard.server.dao.entityview.EntityViewService;
 import org.thingsboard.server.dao.rule.RuleChainService;
 import org.thingsboard.server.dao.tenant.TenantService;
 import org.thingsboard.server.dao.user.UserService;
@@ -47,6 +48,9 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
     private DeviceService deviceService;
 
     @Autowired
+    private EntityViewService entityViewService;
+
+    @Autowired
     private TenantService tenantService;
 
     @Autowired
@@ -81,6 +85,9 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
             case DEVICE:
                 hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId()));
                 break;
+            case ENTITY_VIEW:
+                hasName = entityViewService.findEntityViewByIdAsync(new EntityViewId(entityId.getId()));
+                break;
             case TENANT:
                 hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
                 break;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
index a44a434..0cc6008 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
@@ -105,21 +105,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
         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 && savedEntityView.getKeys().getAttributes() != null) {
-            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;
     }
 
@@ -294,36 +279,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
                 });
     }
 
-    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>() {
 
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
index 1ab7605..fc0ff28 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
@@ -116,8 +116,10 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
                                         }
                                         List<String> filteredAttributes =
                                                 attributes.stream().filter(attr -> attributeContainsInEntityView(scope, attr, entityView)).collect(Collectors.toList());
-                                        ctx.getAttributesService().removeAll(entityView.getId(), scope, filteredAttributes);
-                                        transformAndTellNext(ctx, msg, entityView);
+                                        if (filteredAttributes != null && !filteredAttributes.isEmpty()) {
+                                            ctx.getAttributesService().removeAll(entityView.getId(), scope, filteredAttributes);
+                                            transformAndTellNext(ctx, msg, entityView);
+                                        }
                                     }
                                 }
                             }
@@ -139,19 +141,10 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
     private boolean attributeContainsInEntityView(String scope, String attrKey, EntityView entityView) {
         switch (scope) {
             case DataConstants.CLIENT_SCOPE:
-                if (entityView.getKeys().getAttributes().getCs().isEmpty()) {
-                    return true;
-                }
                 return entityView.getKeys().getAttributes().getCs().contains(attrKey);
             case DataConstants.SERVER_SCOPE:
-                if (entityView.getKeys().getAttributes().getSs().isEmpty()) {
-                    return true;
-                }
                 return entityView.getKeys().getAttributes().getSs().contains(attrKey);
             case DataConstants.SHARED_SCOPE:
-                if (entityView.getKeys().getAttributes().getSh().isEmpty()) {
-                    return true;
-                }
                 return entityView.getKeys().getAttributes().getSh().contains(attrKey);
         }
         return false;
@@ -159,6 +152,5 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
 
     @Override
     public void destroy() {
-
     }
 }
diff --git a/ui/src/app/api/entity.service.js b/ui/src/app/api/entity.service.js
index 205abc9..00c7ecf 100644
--- a/ui/src/app/api/entity.service.js
+++ b/ui/src/app/api/entity.service.js
@@ -135,6 +135,10 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
             case types.entityType.asset:
                 promise = assetService.getAssets(entityIds, config);
                 break;
+            case types.entityType.entityView:
+                promise = getEntitiesByIdsPromise(
+                    (id) => entityViewService.getEntityView(id, config), entityIds);
+                break;
             case types.entityType.tenant:
                 promise = getEntitiesByIdsPromise(
                     (id) => tenantService.getTenant(id, config), entityIds);
diff --git a/ui/src/app/api/entity-view.service.js b/ui/src/app/api/entity-view.service.js
index e34d3a4..23fefbc 100644
--- a/ui/src/app/api/entity-view.service.js
+++ b/ui/src/app/api/entity-view.service.js
@@ -27,7 +27,6 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu
         deleteEntityView: deleteEntityView,
         getCustomerEntityViews: getCustomerEntityViews,
         getEntityView: getEntityView,
-        getEntityViews: getEntityViews,
         getTenantEntityViews: getTenantEntityViews,
         saveEntityView: saveEntityView,
         unassignEntityViewFromCustomer: unassignEntityViewFromCustomer,
@@ -126,32 +125,6 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu
         return deferred.promise;
     }
 
-    function getEntityViews(entityViewIds, config) {
-        var deferred = $q.defer();
-        var ids = '';
-        for (var i=0;i<entityViewIds.length;i++) {
-            if (i>0) {
-                ids += ',';
-            }
-            ids += entityViewIds[i];
-        }
-        var url = '/api/entityViews?entityViewIds=' + ids;
-        $http.get(url, config).then(function success(response) {
-            var entityViews = response.data;
-            entityViews.sort(function (entityView1, entityView2) {
-               var id1 =  entityView1.id.id;
-               var id2 =  entityView2.id.id;
-               var index1 = entityViewIds.indexOf(id1);
-               var index2 = entityViewIds.indexOf(id2);
-               return index1 - index2;
-            });
-            deferred.resolve(entityViews);
-        }, function fail(response) {
-            deferred.reject(response.data);
-        });
-        return deferred.promise;
-    }
-
     function saveEntityView(entityView) {
         var deferred = $q.defer();
         var url = '/api/entityView';