thingsboard-memoizeit

JPA Rule and Plugin DAO added

5/2/2017 12:14:29 AM

Changes

Details

diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
index d3ed5d1..584beed 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
@@ -33,7 +33,7 @@ public class ModelConstants {
      */
     public static final String ID_PROPERTY = "id";
     public static final String USER_ID_PROPERTY = "user_id";
-    public static final String TENTANT_ID_PROPERTY = "tenant_id";
+    public static final String TENANT_ID_PROPERTY = "tenant_id";
     public static final String CUSTOMER_ID_PROPERTY = "customer_id";
     public static final String DEVICE_ID_PROPERTY = "device_id";
     public static final String TITLE_PROPERTY = "title";
@@ -45,7 +45,7 @@ public class ModelConstants {
      * Cassandra user constants.
      */
     public static final String USER_COLUMN_FAMILY_NAME = "user";
-    public static final String USER_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String USER_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String USER_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
     public static final String USER_EMAIL_PROPERTY = "email";
     public static final String USER_AUTHORITY_PROPERTY = "authority";
@@ -106,7 +106,7 @@ public class ModelConstants {
      * Cassandra customer constants.
      */
     public static final String CUSTOMER_COLUMN_FAMILY_NAME = "customer";
-    public static final String CUSTOMER_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String CUSTOMER_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String CUSTOMER_TITLE_PROPERTY = TITLE_PROPERTY;
     public static final String CUSTOMER_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
 
@@ -116,7 +116,7 @@ public class ModelConstants {
      * Cassandra device constants.
      */
     public static final String DEVICE_COLUMN_FAMILY_NAME = "device";
-    public static final String DEVICE_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String DEVICE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String DEVICE_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
     public static final String DEVICE_NAME_PROPERTY = "name";
     public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
@@ -142,7 +142,7 @@ public class ModelConstants {
      * Cassandra widgets_bundle constants.
      */
     public static final String WIDGETS_BUNDLE_COLUMN_FAMILY_NAME = "widgets_bundle";
-    public static final String WIDGETS_BUNDLE_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String WIDGETS_BUNDLE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String WIDGETS_BUNDLE_ALIAS_PROPERTY = ALIAS_PROPERTY;
     public static final String WIDGETS_BUNDLE_TITLE_PROPERTY = TITLE_PROPERTY;
     public static final String WIDGETS_BUNDLE_IMAGE_PROPERTY = "image";
@@ -154,7 +154,7 @@ public class ModelConstants {
      * Cassandra widget_type constants.
      */
     public static final String WIDGET_TYPE_COLUMN_FAMILY_NAME = "widget_type";
-    public static final String WIDGET_TYPE_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String WIDGET_TYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String WIDGET_TYPE_BUNDLE_ALIAS_PROPERTY = "bundle_alias";
     public static final String WIDGET_TYPE_ALIAS_PROPERTY = ALIAS_PROPERTY;
     public static final String WIDGET_TYPE_NAME_PROPERTY = "name";
@@ -166,7 +166,7 @@ public class ModelConstants {
      * Cassandra dashboard constants.
      */
     public static final String DASHBOARD_COLUMN_FAMILY_NAME = "dashboard";
-    public static final String DASHBOARD_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String DASHBOARD_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String DASHBOARD_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
     public static final String DASHBOARD_TITLE_PROPERTY = TITLE_PROPERTY;
     public static final String DASHBOARD_CONFIGURATION_PROPERTY = "configuration";
@@ -179,7 +179,7 @@ public class ModelConstants {
      * Cassandra plugin metadata constants.
      */
     public static final String PLUGIN_COLUMN_FAMILY_NAME = "plugin";
-    public static final String PLUGIN_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String PLUGIN_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String PLUGIN_NAME_PROPERTY = "name";
     public static final String PLUGIN_API_TOKEN_PROPERTY = "api_token";
     public static final String PLUGIN_CLASS_PROPERTY = "plugin_class";
@@ -209,7 +209,7 @@ public class ModelConstants {
      * Cassandra rule metadata constants.
      */
     public static final String RULE_COLUMN_FAMILY_NAME = "rule";
-    public static final String RULE_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String RULE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String RULE_NAME_PROPERTY = "name";
     public static final String RULE_STATE_PROPERTY = "state";
     public static final String RULE_WEIGHT_PROPERTY = "weight";
@@ -225,7 +225,7 @@ public class ModelConstants {
      * Cassandra event constants.
      */
     public static final String EVENT_COLUMN_FAMILY_NAME = "event";
-    public static final String EVENT_TENANT_ID_PROPERTY = TENTANT_ID_PROPERTY;
+    public static final String EVENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String EVENT_TYPE_PROPERTY = "event_type";
     public static final String EVENT_UID_PROPERTY = "event_uid";
     public static final String EVENT_ENTITY_TYPE_PROPERTY = "entity_type";
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
index 239e51d..46f1e32 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
@@ -22,6 +22,9 @@ import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
 import org.thingsboard.server.common.data.id.PluginId;
 import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
@@ -29,23 +32,25 @@ import org.thingsboard.server.common.data.plugin.PluginMetaData;
 import org.thingsboard.server.dao.model.ModelConstants;
 import org.thingsboard.server.dao.model.SearchTextEntity;
 
+import java.io.IOException;
 import java.util.Objects;
 import java.util.UUID;
-
-//@Entity
+@Slf4j
+@Data
+@Entity
 @Table(name = ModelConstants.PLUGIN_COLUMN_FAMILY_NAME)
 public class PluginMetaDataEntity implements SearchTextEntity<PluginMetaData> {
 
     @Transient
     private static final long serialVersionUID = -6164321050824823149L;
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY)
+    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
     private UUID id;
 
     @Column(name = ModelConstants.PLUGIN_API_TOKEN_PROPERTY)
     private String apiToken;
 
-    @Column(name = ModelConstants.PLUGIN_TENANT_ID_PROPERTY)
+    @Column(name = ModelConstants.PLUGIN_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
     private UUID tenantId;
 
     @Column(name = ModelConstants.PLUGIN_NAME_PROPERTY)
@@ -61,13 +66,13 @@ public class PluginMetaDataEntity implements SearchTextEntity<PluginMetaData> {
     private ComponentLifecycleState state;
 
     @Column(name = ModelConstants.PLUGIN_CONFIGURATION_PROPERTY)
-    private JsonNode configuration;
+    private String configuration;
 
     @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
     private String searchText;
 
     @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY)
-    private JsonNode additionalInfo;
+    private String additionalInfo;
 
     public PluginMetaDataEntity() {
     }
@@ -82,9 +87,13 @@ public class PluginMetaDataEntity implements SearchTextEntity<PluginMetaData> {
         this.name = pluginMetaData.getName();
         this.publicAccess = pluginMetaData.isPublicAccess();
         this.state = pluginMetaData.getState();
-        this.configuration = pluginMetaData.getConfiguration();
         this.searchText = pluginMetaData.getName();
-        this.additionalInfo = pluginMetaData.getAdditionalInfo();
+        if (pluginMetaData.getConfiguration() != null) {
+            this.configuration = pluginMetaData.getConfiguration().toString();
+        }
+        if (pluginMetaData.getAdditionalInfo() != null) {
+            this.additionalInfo = pluginMetaData.getAdditionalInfo().toString();
+        }
     }
 
     @Override
@@ -107,86 +116,33 @@ public class PluginMetaDataEntity implements SearchTextEntity<PluginMetaData> {
         this.id = id;
     }
 
-    public String getApiToken() {
-        return apiToken;
-    }
-
-    public void setApiToken(String apiToken) {
-        this.apiToken = apiToken;
-    }
-
-    public UUID getTenantId() {
-        return tenantId;
-    }
-
-    public void setTenantId(UUID tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getClazz() {
-        return clazz;
-    }
-
-    public void setClazz(String clazz) {
-        this.clazz = clazz;
-    }
-
-    public JsonNode getConfiguration() {
-        return configuration;
-    }
-
-    public void setConfiguration(JsonNode configuration) {
-        this.configuration = configuration;
-    }
-
-    public boolean isPublicAccess() {
-        return publicAccess;
-    }
-
-    public void setPublicAccess(boolean publicAccess) {
-        this.publicAccess = publicAccess;
-    }
-
-    public ComponentLifecycleState getState() {
-        return state;
-    }
-
-    public void setState(ComponentLifecycleState state) {
-        this.state = state;
-    }
-
-    public String getSearchText() {
-        return searchText;
-    }
-
-    public JsonNode getAdditionalInfo() {
-        return additionalInfo;
-    }
-
-    public void setAdditionalInfo(JsonNode additionalInfo) {
-        this.additionalInfo = additionalInfo;
-    }
-
     @Override
     public PluginMetaData toData() {
         PluginMetaData data = new PluginMetaData(new PluginId(id));
         data.setTenantId(new TenantId(tenantId));
         data.setCreatedTime(UUIDs.unixTimestamp(id));
         data.setName(name);
-        data.setConfiguration(configuration);
         data.setClazz(clazz);
         data.setPublicAccess(publicAccess);
         data.setState(state);
         data.setApiToken(apiToken);
-        data.setAdditionalInfo(additionalInfo);
+        ObjectMapper mapper = new ObjectMapper();
+        if (configuration != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(configuration);
+                data.setConfiguration(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", configuration, e.getMessage()), e);
+            }
+        }
+        if (additionalInfo != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(additionalInfo);
+                data.setAdditionalInfo(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
+            }
+        }
         return data;
     }
 
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
index 56b8260..54b74b4 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
@@ -16,12 +16,17 @@
 package org.thingsboard.server.dao.model.sql;
 
 import com.datastax.driver.core.utils.UUIDs;
+
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
+
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
 import org.thingsboard.server.common.data.id.RuleId;
 import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
@@ -30,19 +35,22 @@ import org.thingsboard.server.dao.DaoUtil;
 import org.thingsboard.server.dao.model.ModelConstants;
 import org.thingsboard.server.dao.model.SearchTextEntity;
 
+import java.io.IOException;
 import java.util.Objects;
 import java.util.UUID;
 
-//@Entity
+@Slf4j
+@Data
+@Entity
 @Table(name = ModelConstants.RULE_COLUMN_FAMILY_NAME)
 public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
 
     @Transient
     private static final long serialVersionUID = -1506905644259463884L;
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY)
+    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
     private UUID id;
-    @Column(name = ModelConstants.RULE_TENANT_ID_PROPERTY)
+    @Column(name = ModelConstants.RULE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
     private UUID tenantId;
     @Column(name = ModelConstants.RULE_NAME_PROPERTY)
     private String name;
@@ -55,13 +63,13 @@ public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
     @Column(name = ModelConstants.RULE_PLUGIN_TOKEN_PROPERTY)
     private String pluginToken;
     @Column(name = ModelConstants.RULE_FILTERS)
-    private JsonNode filters;
+    private String filters;
     @Column(name = ModelConstants.RULE_PROCESSOR)
-    private JsonNode processor;
+    private String processor;
     @Column(name = ModelConstants.RULE_ACTION)
-    private JsonNode action;
+    private String action;
     @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY)
-    private JsonNode additionalInfo;
+    private String additionalInfo;
 
     public RuleMetaDataEntity() {
     }
@@ -76,10 +84,18 @@ public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
         this.state = rule.getState();
         this.weight = rule.getWeight();
         this.searchText = rule.getName();
-        this.filters = rule.getFilters();
-        this.processor = rule.getProcessor();
-        this.action = rule.getAction();
-        this.additionalInfo = rule.getAdditionalInfo();
+        if (rule.getFilters() != null) {
+            this.filters = rule.getFilters().toString();
+        }
+        if (rule.getProcessor() != null) {
+            this.processor = rule.getProcessor().toString();
+        }
+        if (rule.getAction() != null) {
+            this.action = rule.getAction().toString();
+        }
+        if (rule.getAdditionalInfo() != null) {
+            this.additionalInfo = rule.getAdditionalInfo().toString();
+        }
     }
 
     @Override
@@ -102,82 +118,6 @@ public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
         this.id = id;
     }
 
-    public UUID getTenantId() {
-        return tenantId;
-    }
-
-    public void setTenantId(UUID tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public ComponentLifecycleState getState() {
-        return state;
-    }
-
-    public void setState(ComponentLifecycleState state) {
-        this.state = state;
-    }
-
-    public int getWeight() {
-        return weight;
-    }
-
-    public void setWeight(int weight) {
-        this.weight = weight;
-    }
-
-    public String getPluginToken() {
-        return pluginToken;
-    }
-
-    public void setPluginToken(String pluginToken) {
-        this.pluginToken = pluginToken;
-    }
-
-    public String getSearchText() {
-        return searchText;
-    }
-
-    public JsonNode getFilters() {
-        return filters;
-    }
-
-    public void setFilters(JsonNode filters) {
-        this.filters = filters;
-    }
-
-    public JsonNode getProcessor() {
-        return processor;
-    }
-
-    public void setProcessor(JsonNode processor) {
-        this.processor = processor;
-    }
-
-    public JsonNode getAction() {
-        return action;
-    }
-
-    public void setAction(JsonNode action) {
-        this.action = action;
-    }
-
-    public JsonNode getAdditionalInfo() {
-        return additionalInfo;
-    }
-
-    public void setAdditionalInfo(JsonNode additionalInfo) {
-        this.additionalInfo = additionalInfo;
-    }
-
     @Override
     public RuleMetaData toData() {
         RuleMetaData rule = new RuleMetaData(new RuleId(id));
@@ -187,10 +127,39 @@ public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
         rule.setWeight(weight);
         rule.setCreatedTime(UUIDs.unixTimestamp(id));
         rule.setPluginToken(pluginToken);
-        rule.setFilters(filters);
-        rule.setProcessor(processor);
-        rule.setAction(action);
-        rule.setAdditionalInfo(additionalInfo);
+        ObjectMapper mapper = new ObjectMapper();
+        if (filters != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(filters);
+                rule.setFilters(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", filters, e.getMessage()), e);
+            }
+        }
+        if (processor != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(processor);
+                rule.setProcessor(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", processor, e.getMessage()), e);
+            }
+        }
+        if (action != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(action);
+                rule.setAction(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", action, e.getMessage()), e);
+            }
+        }
+        if (additionalInfo != null) {
+            try {
+                JsonNode jsonNode = mapper.readTree(additionalInfo);
+                rule.setAdditionalInfo(jsonNode);
+            } catch (IOException e) {
+                log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e);
+            }
+        }
         return rule;
     }
 
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
index 6c54fd0..aa388d2 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
@@ -1,12 +1,12 @@
 /**
  * Copyright © 2016-2017 The Thingsboard Authors
- * <p>
+ *
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
index 7900891..00ff205 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
@@ -25,6 +25,7 @@ import javax.persistence.Transient;
 import com.datastax.driver.mapping.annotations.PartitionKey;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.id.WidgetTypeId;
@@ -36,6 +37,7 @@ import java.io.IOException;
 import java.util.UUID;
 
 @Slf4j
+@Data
 @Entity
 @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME)
 public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
@@ -93,46 +95,6 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
         this.id = id;
     }
 
-    public UUID getTenantId() {
-        return tenantId;
-    }
-
-    public void setTenantId(UUID tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public String getBundleAlias() {
-        return bundleAlias;
-    }
-
-    public void setBundleAlias(String bundleAlias) {
-        this.bundleAlias = bundleAlias;
-    }
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescriptor() {
-        return descriptor;
-    }
-
-    public void setDescriptor(String descriptor) {
-        this.descriptor = descriptor;
-    }
-
     @Override
     public int hashCode() {
         int result = id != null ? id.hashCode() : 0;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
index 414c213..8d064c3 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
@@ -1,12 +1,12 @@
 /**
  * Copyright © 2016-2017 The Thingsboard Authors
- * <p>
+ *
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java
new file mode 100644
index 0000000..5134ae6
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java
@@ -0,0 +1,140 @@
+/**
+ * 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.sql.plugin;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.id.PluginId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.data.plugin.PluginMetaData;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity;
+import org.thingsboard.server.dao.plugin.PluginDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/1/2017.
+ */
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, PluginMetaData> implements PluginDao {
+
+    @Autowired
+    private PluginMetaDataRepository pluginMetaDataRepository;
+
+    @Override
+    protected Class<PluginMetaDataEntity> getEntityClass() {
+        return PluginMetaDataEntity.class;
+    }
+
+    @Override
+    protected String getColumnFamilyName() {
+        return ModelConstants.PLUGIN_COLUMN_FAMILY_NAME;
+    }
+
+    @Override
+    protected CrudRepository<PluginMetaDataEntity, UUID> getCrudRepository() {
+        return pluginMetaDataRepository;
+    }
+
+    @Override
+    protected boolean isSearchTextDao() {
+        return true;
+    }
+
+    @Override
+    public PluginMetaData findById(PluginId pluginId) {
+        log.debug("Search plugin meta-data entity by id [{}]", pluginId);
+        PluginMetaData pluginMetaData = super.findById(pluginId.getId());
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}] for plugin entity [{}]", pluginMetaData != null, pluginMetaData);
+        } else {
+            log.debug("Search result: [{}]", pluginMetaData != null);
+        }
+        return pluginMetaData;
+    }
+
+    @Override
+    public PluginMetaData findByApiToken(String apiToken) {
+        log.debug("Search plugin meta-data entity by api token [{}]", apiToken);
+        PluginMetaDataEntity entity = pluginMetaDataRepository.findByApiToken(apiToken);
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}] for plugin entity [{}]", entity != null, entity);
+        } else {
+            log.debug("Search result: [{}]", entity != null);
+        }
+        return DaoUtil.getData(entity);
+    }
+
+    @Override
+    public void deleteById(UUID id) {
+        log.debug("Delete plugin meta-data entity by id [{}]", id);
+        pluginMetaDataRepository.delete(id);
+    }
+
+    @Override
+    public void deleteById(PluginId pluginId) {
+        deleteById(pluginId.getId());
+    }
+
+    @Override
+    public List<PluginMetaData> findByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink) {
+        log.debug("Try to find здгпшты by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
+        List<PluginMetaDataEntity> entities;
+        if (pageLink.getIdOffset() == null) {
+            entities = pluginMetaDataRepository
+                    .findByTenantIdAndPageLinkFirstPage(pageLink.getLimit(), tenantId.getId(), pageLink.getTextSearch());
+        } else {
+            entities = pluginMetaDataRepository
+                    .findByTenantIdAndPageLinkNextPage(pageLink.getLimit(), tenantId.getId(), pageLink.getTextSearch(), pageLink.getIdOffset());
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}]", Arrays.toString(entities.toArray()));
+        } else {
+            log.debug("Search result: [{}]", entities.size());
+        }
+        return DaoUtil.convertDataList(entities);
+    }
+
+    @Override
+    public List<PluginMetaData> findAllTenantPluginsByTenantId(UUID tenantId, TextPageLink pageLink) {
+        log.debug("Try to find all tenant plugins by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
+        List<PluginMetaDataEntity> entities;
+        if (pageLink.getIdOffset() == null) {
+            entities = pluginMetaDataRepository
+                    .findAllTenantPluginsByTenantIdFirstPage(pageLink.getLimit(), tenantId, pageLink.getTextSearch());
+        } else {
+            entities = pluginMetaDataRepository
+                    .findAllTenantPluginsByTenantIdNextPage(pageLink.getLimit(), tenantId, pageLink.getTextSearch(), pageLink.getIdOffset());
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}]", Arrays.toString(entities.toArray()));
+        } else {
+            log.debug("Search result: [{}]", entities.size());
+        }
+        return DaoUtil.convertDataList(entities);
+    }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/PluginMetaDataRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/PluginMetaDataRepository.java
new file mode 100644
index 0000000..315042b
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/PluginMetaDataRepository.java
@@ -0,0 +1,55 @@
+/**
+ * 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.sql.plugin;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.common.data.plugin.PluginMetaData;
+import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity;
+import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/1/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface PluginMetaDataRepository extends CrudRepository<PluginMetaDataEntity, UUID> {
+
+    PluginMetaDataEntity findByApiToken(String apiToken);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM PLUGIN WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<PluginMetaDataEntity> findByTenantIdAndPageLinkFirstPage(int limit, UUID tenantId, String textSearch);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM PLUGIN WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "AND ID > ?4 ORDER BY ID LIMIT ?1")
+    List<PluginMetaDataEntity> findByTenantIdAndPageLinkNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM PLUGIN WHERE (TENANT_ID = ?2 OR TENANT_ID IS NULL) " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<PluginMetaDataEntity> findAllTenantPluginsByTenantIdFirstPage(int limit, UUID tenantId, String textSearch);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM PLUGIN WHERE (TENANT_ID = ?2 OR TENANT_ID IS NULL) " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "AND ID > ?4 ORDER BY ID LIMIT ?1")
+    List<PluginMetaDataEntity> findAllTenantPluginsByTenantIdNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset);
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java
new file mode 100644
index 0000000..b2a5d12
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java
@@ -0,0 +1,126 @@
+/**
+ * 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.sql.rule;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.id.RuleId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.data.rule.RuleMetaData;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity;
+import org.thingsboard.server.dao.rule.RuleDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaData> implements RuleDao {
+
+    @Autowired
+    private RuleMetaDataRepository ruleMetaDataRepository;
+
+    @Override
+    protected Class<RuleMetaDataEntity> getEntityClass() {
+        return RuleMetaDataEntity.class;
+    }
+    @Override
+    protected String getColumnFamilyName() {
+        return ModelConstants.RULE_COLUMN_FAMILY_NAME;
+    }
+
+    @Override
+    protected CrudRepository<RuleMetaDataEntity, UUID> getCrudRepository() {
+        return ruleMetaDataRepository;
+    }
+
+    @Override
+    protected boolean isSearchTextDao() {
+        return true;
+    }
+
+    @Override
+    public RuleMetaData findById(RuleId ruleId) {
+        return findById(ruleId.getId());
+    }
+
+    @Override
+    public List<RuleMetaData> findRulesByPlugin(String pluginToken) {
+        log.debug("Search rules by api token [{}]", pluginToken);
+        return DaoUtil.convertDataList(ruleMetaDataRepository.findByPluginToken(pluginToken));
+    }
+
+    @Override
+    public List<RuleMetaData> findByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink) {
+        log.debug("Try to find rules by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
+        List<RuleMetaDataEntity> entities;
+        if (pageLink.getIdOffset() == null) {
+            entities = ruleMetaDataRepository
+                    .findByTenantIdAndPageLinkFirstPage(pageLink.getLimit(), tenantId.getId(), pageLink.getTextSearch());
+        } else {
+            entities = ruleMetaDataRepository
+                    .findByTenantIdAndPageLinkNextPage(pageLink.getLimit(), tenantId.getId(), pageLink.getTextSearch(), pageLink.getIdOffset());
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}]", Arrays.toString(entities.toArray()));
+        } else {
+            log.debug("Search result: [{}]", entities.size());
+        }
+        return DaoUtil.convertDataList(entities);
+    }
+
+    @Override
+    public List<RuleMetaData> findAllTenantRulesByTenantId(UUID tenantId, TextPageLink pageLink) {
+        log.debug("Try to find all tenant rules by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
+        List<RuleMetaDataEntity> entities;
+        if (pageLink.getIdOffset() == null) {
+            entities = ruleMetaDataRepository
+                    .findAllTenantRulesByTenantIdFirstPage(pageLink.getLimit(), tenantId, pageLink.getTextSearch());
+        } else {
+            entities = ruleMetaDataRepository
+                    .findAllTenantRulesByTenantIdNextPage(pageLink.getLimit(), tenantId, pageLink.getTextSearch(), pageLink.getIdOffset());
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Search result: [{}]", Arrays.toString(entities.toArray()));
+        } else {
+            log.debug("Search result: [{}]", entities.size());
+        }
+        return DaoUtil.convertDataList(entities);
+    }
+
+    @Override
+    public void deleteById(UUID id) {
+        log.debug("Delete rule meta-data entity by id [{}]", id);
+        ruleMetaDataRepository.delete(id);
+    }
+
+    @Override
+    public void deleteById(RuleId ruleId) {
+        deleteById(ruleId.getId());
+    }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleMetaDataRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleMetaDataRepository.java
new file mode 100644
index 0000000..1a3b143
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleMetaDataRepository.java
@@ -0,0 +1,56 @@
+/**
+ * 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.sql.rule;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.dao.model.ToData;
+import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface RuleMetaDataRepository extends CrudRepository<RuleMetaDataEntity, UUID> {
+
+    List<RuleMetaDataEntity> findByPluginToken(String pluginToken);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM RULE WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<RuleMetaDataEntity> findByTenantIdAndPageLinkFirstPage(int limit, UUID tenantId, String textSearch);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM RULE WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "AND ID > ?4 ORDER BY ID LIMIT ?1")
+    List<RuleMetaDataEntity> findByTenantIdAndPageLinkNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM RULE WHERE (TENANT_ID = ?2 OR TENANT_ID IS NULL) " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<RuleMetaDataEntity> findAllTenantRulesByTenantIdFirstPage(int limit, UUID tenantId, String textSearch);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM RULE WHERE (TENANT_ID = ?2 OR TENANT_ID IS NULL) " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "AND ID > ?4 ORDER BY ID LIMIT ?1")
+    List<RuleMetaDataEntity> findAllTenantRulesByTenantIdNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset);
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
index 7cdb727..0f34109 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.tenant;
 
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java
index ec533f4..6c94072 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.tenant;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
index cffccdb..3008f59 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
@@ -1,12 +1,12 @@
 /**
  * Copyright © 2016-2017 The Thingsboard Authors
- * <p>
+ *
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
index cc4df06..de32f06 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
@@ -1,12 +1,12 @@
 /**
  * Copyright © 2016-2017 The Thingsboard Authors
- * <p>
+ *
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
index 9cc89b2..2146a8f 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.widget;
 
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
index 5b33617..6161d12 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.widget;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java
new file mode 100644
index 0000000..f968b68
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.sql.plugin;
+
+import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.id.PluginId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.data.plugin.PluginMetaData;
+import org.thingsboard.server.common.data.rule.RuleMetaData;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.plugin.PluginDao;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Created by Valerii Sosliuk on 5/1/2017.
+ */
+public class JpaBasePluginDaoTest extends AbstractJpaDaoTest {
+
+    @Autowired
+    private PluginDao pluginDao;
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    public void testFindByTenantIdAndPageLink() {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        createPluginsTwoTenants(tenantId1, tenantId2, "plugin_");
+        assertEquals(60, pluginDao.find().size());
+        List<PluginMetaData> rules1 = pluginDao.findByTenantIdAndPageLink(
+                new TenantId(tenantId1), new TextPageLink(20, "plugin_"));
+        assertEquals(20, rules1.size());
+
+        List<PluginMetaData> rules2 = pluginDao.findByTenantIdAndPageLink(new TenantId(tenantId1),
+                new TextPageLink(20, "plugin_", rules1.get(19).getId().getId(), null));
+        assertEquals(10, rules2.size());
+
+        List<PluginMetaData> rules3 = pluginDao.findByTenantIdAndPageLink(new TenantId(tenantId1),
+                new TextPageLink(20, "plugin_", rules2.get(9).getId().getId(), null));
+        assertEquals(0, rules3.size());
+    }
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    public void testFindAllTenantRulesByTenantId() {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        createTenantsAndSystemPlugins(tenantId1, tenantId2, "name_");
+        List<PluginMetaData> rules1 = pluginDao.findAllTenantPluginsByTenantId(
+                tenantId1, new TextPageLink(40, "name_"));
+        assertEquals(40, rules1.size());
+
+        List<PluginMetaData> rules2 = pluginDao.findAllTenantPluginsByTenantId(tenantId1,
+                new TextPageLink(40, "name_", rules1.get(39).getId().getId(), null));
+        assertEquals(20, rules2.size());
+
+        List<PluginMetaData> rules3 = pluginDao.findAllTenantPluginsByTenantId(tenantId1,
+                new TextPageLink(40, "name_", rules2.get(19).getId().getId(), null));
+        assertEquals(0, rules3.size());
+    }
+
+    private void createTenantsAndSystemPlugins(UUID tenantId1, UUID tenantId2, String namePrefix) {
+        for (int i = 0; i < 30; i++) {
+            createPlugin(tenantId1, namePrefix, i);
+            createPlugin(tenantId2, namePrefix, i);
+            createPlugin(null, namePrefix, i);
+        }
+    }
+
+    private void createPluginsTwoTenants(UUID tenantId1, UUID tenantId2, String namePrefix) {
+        for (int i = 0; i < 30; i++) {
+            createPlugin(tenantId1, namePrefix, i);
+            createPlugin(tenantId2, namePrefix, i);
+        }
+    }
+
+    private void createPlugin(UUID tenantId, String namePrefix, int i) {
+        PluginMetaData plugin = new PluginMetaData();
+        plugin.setId(new PluginId(UUIDs.timeBased()));
+        plugin.setTenantId(new TenantId(tenantId));
+        plugin.setName(namePrefix + i);
+        pluginDao.save(plugin);
+    }
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java
new file mode 100644
index 0000000..9e2141d
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java
@@ -0,0 +1,110 @@
+/**
+ * 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.sql.rule;
+
+import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.id.RuleId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.data.rule.RuleMetaData;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.rule.RuleDao;
+
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Created by Valerii Sosliuk on 4/30/2017.
+ */
+public class JpaBaseRuleDaoTest extends AbstractJpaDaoTest {
+
+    @Autowired
+    private RuleDao jpaBaseRuleDao;
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/rule.xml")
+    public void testFindRulesByPlugin() {
+        assertEquals(3, jpaBaseRuleDao.findRulesByPlugin("token_1").size());
+    }
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    public void testFindByTenantIdAndPageLink() {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        createRulesTwoTenants(tenantId1, tenantId2, "name_", "token");
+        List<RuleMetaData> rules1 = jpaBaseRuleDao.findByTenantIdAndPageLink(
+                new TenantId(tenantId1), new TextPageLink(20, "name_"));
+        assertEquals(20, rules1.size());
+
+        List<RuleMetaData> rules2 = jpaBaseRuleDao.findByTenantIdAndPageLink(new TenantId(tenantId1),
+                new TextPageLink(20, "name_", rules1.get(19).getId().getId(), null));
+        assertEquals(10, rules2.size());
+
+        List<RuleMetaData> rules3 = jpaBaseRuleDao.findByTenantIdAndPageLink(new TenantId(tenantId1),
+                new TextPageLink(20, "name_", rules2.get(9).getId().getId(), null));
+        assertEquals(0, rules3.size());
+    }
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    public void testFindAllTenantRulesByTenantId() {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        createTenantsAndSystemRules(tenantId1, tenantId2, "name_", "token");
+        List<RuleMetaData> rules1 = jpaBaseRuleDao.findAllTenantRulesByTenantId(
+                tenantId1, new TextPageLink(40, "name_"));
+        assertEquals(40, rules1.size());
+
+        List<RuleMetaData> rules2 = jpaBaseRuleDao.findAllTenantRulesByTenantId(tenantId1,
+                new TextPageLink(40, "name_", rules1.get(39).getId().getId(), null));
+        assertEquals(20, rules2.size());
+
+        List<RuleMetaData> rules3 = jpaBaseRuleDao.findAllTenantRulesByTenantId(tenantId1,
+                new TextPageLink(40, "name_", rules2.get(19).getId().getId(), null));
+        assertEquals(0, rules3.size());
+    }
+
+    private void createRulesTwoTenants(UUID tenantId1, UUID tenantId2, String namePrefix, String pluginToken) {
+        for (int i = 0; i < 30; i++) {
+            createRule(tenantId1, namePrefix, pluginToken, i);
+            createRule(tenantId2, namePrefix, pluginToken, i);
+        }
+    }
+
+    private void createTenantsAndSystemRules(UUID tenantId1, UUID tenantId2, String namePrefix, String pluginToken) {
+        for (int i = 0; i < 30; i++) {
+            createRule(tenantId1, namePrefix, pluginToken, i);
+            createRule(tenantId2, namePrefix, pluginToken, i);
+            createRule(null, namePrefix, pluginToken, i);
+        }
+    }
+
+    private void createRule(UUID tenantId, String namePrefix, String pluginToken, int i) {
+        RuleMetaData ruleMetaData = new RuleMetaData();
+        ruleMetaData.setId(new RuleId(UUIDs.timeBased()));
+        ruleMetaData.setTenantId(new TenantId(tenantId));
+        ruleMetaData.setName(namePrefix + i);
+        ruleMetaData.setPluginToken(pluginToken);
+        jpaBaseRuleDao.save(ruleMetaData);
+    }
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java
index 2515618..4b3555a 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDaoTest.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.tenant;
 
 import com.datastax.driver.core.utils.UUIDs;
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
index c41a7c5..c38ccbd 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
@@ -1,3 +1,18 @@
+/**
+ * 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.sql.widget;
 
 import com.datastax.driver.core.utils.UUIDs;
diff --git a/dao/src/test/resources/dbunit/rule.xml b/dao/src/test/resources/dbunit/rule.xml
new file mode 100644
index 0000000..dfe1054
--- /dev/null
+++ b/dao/src/test/resources/dbunit/rule.xml
@@ -0,0 +1,34 @@
+<dataset>
+    <rule
+        id="uuid'8e834e11-2e0a-11e7-83ec-f7f6dbfb4833'"
+        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        name="RULE_11"
+        weight="1"
+        search_text="rule_11"
+        plugin_token="token_1"
+    />
+    <rule
+        id="uuid'8e834e12-2e0a-11e7-83ec-f7f6dbfb4833'"
+        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        name="RULE_12"
+        weight="1"
+        search_text="rule_12"
+        plugin_token="token_1"
+    />
+    <rule
+        id="uuid'8e834e13-2e0a-11e7-83ec-f7f6dbfb4833'"
+        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        name="RULE_13"
+        weight="1"
+        search_text="rule_13"
+        plugin_token="token_1"
+    />
+    <rule
+        id="uuid'8e834e14-2e0a-11e7-83ec-f7f6dbfb4833'"
+        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        name="RULE_14"
+        weight="2"
+        search_text="rule_14"
+        plugin_token="token_2"
+    />
+</dataset>
\ No newline at end of file