/** * Copyright © 2016-2017 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.dao.component; import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.jsonschema.core.exceptions.ProcessingException; import com.github.fge.jsonschema.core.report.ProcessingReport; import com.github.fge.jsonschema.main.JsonSchemaFactory; import com.github.fge.jsonschema.main.JsonValidator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.id.ComponentDescriptorId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentScope; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ComponentDescriptorEntity; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.Validator; import java.util.List; import java.util.Optional; import static org.thingsboard.server.dao.DaoUtil.convertDataList; import static org.thingsboard.server.dao.DaoUtil.getData; /** * @author Andrew Shvayka */ @Service @Slf4j public class BaseComponentDescriptorService implements ComponentDescriptorService { @Autowired private ComponentDescriptorDao componentDescriptorDao; @Override public ComponentDescriptor saveComponent(ComponentDescriptor component) { componentValidator.validate(component); Optional<ComponentDescriptorEntity> result = componentDescriptorDao.save(component); if (result.isPresent()) { return getData(result.get()); } else { return getData(componentDescriptorDao.findByClazz(component.getClazz())); } } @Override public ComponentDescriptor findById(ComponentDescriptorId componentId) { Validator.validateId(componentId, "Incorrect component id for search request."); return getData(componentDescriptorDao.findById(componentId)); } @Override public ComponentDescriptor findByClazz(String clazz) { Validator.validateString(clazz, "Incorrect clazz for search request."); return getData(componentDescriptorDao.findByClazz(clazz)); } @Override public TextPageData<ComponentDescriptor> findByTypeAndPageLink(ComponentType type, TextPageLink pageLink) { Validator.validatePageLink(pageLink, "Incorrect PageLink object for search plugin components request."); List<ComponentDescriptorEntity> pluginEntities = componentDescriptorDao.findByTypeAndPageLink(type, pageLink); List<ComponentDescriptor> components = convertDataList(pluginEntities); return new TextPageData<>(components, pageLink); } @Override public TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(ComponentScope scope, ComponentType type, TextPageLink pageLink) { Validator.validatePageLink(pageLink, "Incorrect PageLink object for search plugin components request."); List<ComponentDescriptorEntity> pluginEntities = componentDescriptorDao.findByScopeAndTypeAndPageLink(scope, type, pageLink); List<ComponentDescriptor> components = convertDataList(pluginEntities); return new TextPageData<>(components, pageLink); } @Override public void deleteByClazz(String clazz) { Validator.validateString(clazz, "Incorrect clazz for delete request."); componentDescriptorDao.deleteByClazz(clazz); } @Override public boolean validate(ComponentDescriptor component, JsonNode configuration) { JsonValidator validator = JsonSchemaFactory.byDefault().getValidator(); try { if (!component.getConfigurationDescriptor().has("schema")) { throw new DataValidationException("Configuration descriptor doesn't contain schema property!"); } JsonNode configurationSchema = component.getConfigurationDescriptor().get("schema"); ProcessingReport report = validator.validate(configurationSchema, configuration); return report.isSuccess(); } catch (ProcessingException e) { throw new IncorrectParameterException(e.getMessage(), e); } } private DataValidator<ComponentDescriptor> componentValidator = new DataValidator<ComponentDescriptor>() { @Override protected void validateDataImpl(ComponentDescriptor plugin) { if (plugin.getType() == null) { throw new DataValidationException("Component type should be specified!."); } if (plugin.getScope() == null) { throw new DataValidationException("Component scope should be specified!."); } if (StringUtils.isEmpty(plugin.getName())) { throw new DataValidationException("Component name should be specified!."); } if (StringUtils.isEmpty(plugin.getClazz())) { throw new DataValidationException("Component clazz should be specified!."); } } }; }