Java tutorial
/** * Copyright 2016-2018 The Thingsboard Authors * * 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. */ 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; 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.DataConstants; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; 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.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.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; /** * Created by Victor Basanets on 8/28/2017. */ @RestController @RequestMapping("/api") @Slf4j public class EntityViewController extends BaseController { public static final String ENTITY_VIEW_ID = "entityViewId"; @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 { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId))); } catch (Exception e) { throw handleException(e); } } @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView", method = RequestMethod.POST) @ResponseBody public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { 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; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); throw handleException(e); } } 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(getTenantId(), 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(entityView.getTenantId(), 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); } } @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) public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); EntityView entityView = checkEntityViewId(entityViewId); entityViewService.deleteEntityView(getTenantId(), entityViewId); logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED, null, strEntityViewId); } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, null, ActionType.DELETED, e, strEntityViewId); throw handleException(e); } } @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/entityViews", params = { "entityViewName" }, method = RequestMethod.GET) @ResponseBody public EntityView getTenantEntityView(@RequestParam String entityViewName) throws ThingsboardException { try { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(entityViewService.findEntityViewByTenantIdAndName(tenantId, entityViewName)); } catch (Exception e) { throw handleException(e); } } @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST) @ResponseBody public EntityView assignEntityViewToCustomer(@PathVariable(CUSTOMER_ID) String strCustomerId, @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); Customer customer = checkCustomerId(customerId); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); checkEntityViewId(entityViewId); EntityView savedEntityView = checkNotNull( entityViewService.assignEntityViewToCustomer(getTenantId(), 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, null, ActionType.ASSIGNED_TO_CUSTOMER, e, strEntityViewId, strCustomerId); throw handleException(e); } } @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE) @ResponseBody public EntityView unassignEntityViewFromCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); EntityView entityView = checkEntityViewId(entityViewId); if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { throw new IncorrectParameterException("Entity View isn't assigned to any customer!"); } Customer customer = checkCustomerId(entityView.getCustomerId()); EntityView savedEntityView = checkNotNull( entityViewService.unassignEntityViewFromCustomer(getTenantId(), entityViewId)); logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName()); return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, null, ActionType.UNASSIGNED_FROM_CUSTOMER, e, strEntityViewId); throw handleException(e); } } @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/entityViews", params = { "limit" }, method = RequestMethod.GET) @ResponseBody public TextPageData<EntityView> getCustomerEntityViews(@PathVariable("customerId") String strCustomerId, @RequestParam int limit, @RequestParam(required = false) String type, @RequestParam(required = false) String textSearch, @RequestParam(required = false) String idOffset, @RequestParam(required = false) String textOffset) throws ThingsboardException { checkParameter("customerId", strCustomerId); try { TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId); TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); } else { return checkNotNull( entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); } } catch (Exception e) { throw handleException(e); } } @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/entityViews", params = { "limit" }, method = RequestMethod.GET) @ResponseBody public TextPageData<EntityView> getTenantEntityViews(@RequestParam int limit, @RequestParam(required = false) String type, @RequestParam(required = false) String textSearch, @RequestParam(required = false) String idOffset, @RequestParam(required = false) String textOffset) throws ThingsboardException { try { TenantId tenantId = getCurrentUser().getTenantId(); TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type)); } else { return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink)); } } catch (Exception e) { throw handleException(e); } } @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityViews", method = RequestMethod.POST) @ResponseBody public List<EntityView> findByQuery(@RequestBody EntityViewSearchQuery query) throws ThingsboardException { checkNotNull(query); checkNotNull(query.getParameters()); checkNotNull(query.getEntityViewTypes()); checkEntityId(query.getParameters().getEntityId()); try { List<EntityView> entityViews = checkNotNull( entityViewService.findEntityViewsByQuery(getTenantId(), query).get()); entityViews = entityViews.stream().filter(entityView -> { try { checkEntityView(entityView); return true; } catch (ThingsboardException e) { return false; } }).collect(Collectors.toList()); return entityViews; } catch (Exception e) { throw handleException(e); } } @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/types", method = RequestMethod.GET) @ResponseBody public List<EntitySubtype> getEntityViewTypes() throws ThingsboardException { try { SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); ListenableFuture<List<EntitySubtype>> entityViewTypes = entityViewService .findEntityViewTypesByTenantId(tenantId); return checkNotNull(entityViewTypes.get()); } catch (Exception e) { throw handleException(e); } } }