Repository: ambari
Updated Branches:
  refs/heads/trunk 6e67329b8 -> 308a618f4


AMBARI-10212. Widgets: Add schema tables for PostgreSQL, MySQL and Oracle.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/308a618f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/308a618f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/308a618f

Branch: refs/heads/trunk
Commit: 308a618f40f3c724dbbd33c178ebbab2c38b2ea4
Parents: 6e67329
Author: Siddharth Wagle <swa...@hortonworks.com>
Authored: Wed Mar 25 17:22:58 2015 -0700
Committer: Siddharth Wagle <swa...@hortonworks.com>
Committed: Wed Mar 25 17:22:58 2015 -0700

----------------------------------------------------------------------
 .../ambari/server/orm/dao/UserWidgetDAO.java    |  99 +++++++++
 .../ambari/server/orm/dao/WidgetLayoutDAO.java  |  99 +++++++++
 .../server/orm/entities/UserWidgetEntity.java   | 222 +++++++++++++++++++
 .../server/orm/entities/WidgetLayoutEntity.java | 130 +++++++++++
 .../entities/WidgetLayoutUserWidgetEntity.java  | 114 ++++++++++
 .../WidgetLayoutUserWidgetEntityPK.java         |  71 ++++++
 .../server/upgrade/UpgradeCatalog210.java       |  40 ++++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  34 +++
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  34 +++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  34 +++
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  37 ++++
 .../src/main/resources/META-INF/persistence.xml |   3 +
 .../server/orm/dao/UserWidgetDAOTest.java       | 116 ++++++++++
 .../server/orm/dao/WidgetLayoutDAOTest.java     | 128 +++++++++++
 .../server/upgrade/UpgradeCatalog210Test.java   |  36 ++-
 15 files changed, 1196 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
new file mode 100644
index 0000000..834da26
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserWidgetDAO.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.UserWidgetEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class UserWidgetDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * DAO utilities for dealing mostly with {@link TypedQuery} results.
+   */
+  @Inject
+  private DaoUtils daoUtils;
+
+  @RequiresSession
+  public UserWidgetEntity findById(Long id) {
+    return entityManagerProvider.get().find(UserWidgetEntity.class, id);
+  }
+
+  @RequiresSession
+  public List<UserWidgetEntity> findByCluster(long clusterId) {
+    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("UserWidgetEntity.findByCluster", 
UserWidgetEntity.class);
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<UserWidgetEntity> findBySectionName(String sectionName) {
+    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("UserWidgetEntity.findBySectionName", 
UserWidgetEntity.class);
+    query.setParameter("sectionName", sectionName);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<UserWidgetEntity> findAll() {
+    TypedQuery<UserWidgetEntity> query = entityManagerProvider.get()
+            .createNamedQuery("UserWidgetEntity.findAll", 
UserWidgetEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  @Transactional
+  public void create(UserWidgetEntity userWidgetEntity) {
+    entityManagerProvider.get().persist(userWidgetEntity);
+  }
+
+  @Transactional
+  public UserWidgetEntity merge(UserWidgetEntity userWidgetEntity) {
+    return entityManagerProvider.get().merge(userWidgetEntity);
+  }
+
+  @Transactional
+  public void remove(UserWidgetEntity userWidgetEntity) {
+    entityManagerProvider.get().remove(merge(userWidgetEntity));
+  }
+
+  @Transactional
+  public void removeByPK(Long id) {
+    entityManagerProvider.get().remove(findById(id));
+  }
+
+  @Transactional
+  public void refresh(UserWidgetEntity userWidgetEntity) {
+    entityManagerProvider.get().refresh(userWidgetEntity);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
new file mode 100644
index 0000000..55e7513
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAO.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.UserWidgetEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class WidgetLayoutDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * DAO utilities for dealing mostly with {@link TypedQuery} results.
+   */
+  @Inject
+  private DaoUtils daoUtils;
+
+  @RequiresSession
+  public WidgetLayoutEntity findById(Long id) {
+    return entityManagerProvider.get().find(WidgetLayoutEntity.class, id);
+  }
+
+  @RequiresSession
+  public List<WidgetLayoutEntity> findByCluster(long clusterId) {
+    TypedQuery<WidgetLayoutEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetLayoutEntity.findByCluster", 
WidgetLayoutEntity.class);
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<WidgetLayoutEntity> findBySectionName(String sectionName) {
+    TypedQuery<WidgetLayoutEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetLayoutEntity.findBySectionName", 
WidgetLayoutEntity.class);
+    query.setParameter("sectionName", sectionName);
+
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<WidgetLayoutEntity> findAll() {
+    TypedQuery<WidgetLayoutEntity> query = entityManagerProvider.get()
+            .createNamedQuery("WidgetLayoutEntity.findAll", 
WidgetLayoutEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  @Transactional
+  public void create(WidgetLayoutEntity widgetLayoutEntity) {
+    entityManagerProvider.get().persist(widgetLayoutEntity);
+  }
+
+  @Transactional
+  public WidgetLayoutEntity merge(WidgetLayoutEntity widgetLayoutEntity) {
+    return entityManagerProvider.get().merge(widgetLayoutEntity);
+  }
+
+  @Transactional
+  public void remove(WidgetLayoutEntity widgetLayoutEntity) {
+    entityManagerProvider.get().remove(merge(widgetLayoutEntity));
+  }
+
+  @Transactional
+  public void removeByPK(Long id) {
+    entityManagerProvider.get().remove(findById(id));
+  }
+
+  @Transactional
+  public void refresh(WidgetLayoutEntity widgetLayoutEntity) {
+    entityManagerProvider.get().refresh(widgetLayoutEntity);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
new file mode 100644
index 0000000..ec84181
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UserWidgetEntity.java
@@ -0,0 +1,222 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.List;
+
+@Entity
+@Table(name = "user_widget")
+@NamedQueries({
+    @NamedQuery(name = "UserWidgetEntity.findAll", query = "SELECT userWidget 
FROM UserWidgetEntity userWidget"),
+    @NamedQuery(name = "UserWidgetEntity.findByCluster", query = "SELECT 
userWidget FROM UserWidgetEntity userWidget WHERE userWidget.clusterId = 
:clusterId"),
+    @NamedQuery(name = "UserWidgetEntity.findBySectionName", query =
+                "SELECT userWidget FROM UserWidgetEntity userWidget " +
+                "INNER JOIN userWidget.listWidgetLayoutUserWidgetEntity 
widgetLayoutUserWidget " +
+                "INNER JOIN widgetLayoutUserWidget.widgetLayout  widgetLayout 
" +
+                "WHERE widgetLayout.sectionName = :sectionName")
+        })
+public class UserWidgetEntity {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "id", nullable = false, updatable = false)
+  private Long id;
+
+  @Column(name = "user_widget_name", nullable = false, length = 255)
+  private String userWidgetName;
+
+  @Column(name = "user_widget_type", nullable = false, length = 255)
+  private String userWidgetType;
+
+  @Column(name = "metrics", length = 32672)
+  private String metrics;
+
+  @Column(name = "time_created", nullable = false, length = 255)
+  private Long timeCreated = System.currentTimeMillis();
+
+  @Column(name = "author", length = 255)
+  private String author;
+
+  @Column(name = "description", length = 255)
+  private String description;
+
+  @Column(name = "display_name", nullable = false,  length = 255)
+  private String displayName;
+
+  @Column(name = "scope", length = 255)
+  private String scope;
+
+  @Column(name = "widget_values", length = 255)
+  private String widgetValues;
+
+  @Column(name = "properties", length = 255)
+  private String properties;
+
+  @Column(name = "cluster_id", nullable = false)
+  private Long clusterId;
+
+  @ManyToOne
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", 
nullable = false, updatable = false, insertable = false)
+  private ClusterEntity clusterEntity;
+
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "userWidget")
+  private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getUserWidgetName() {
+    return userWidgetName;
+  }
+
+  public void setUserWidgetName(String userWidgetName) {
+    this.userWidgetName = userWidgetName;
+  }
+
+  public String getUserWidgetType() {
+    return userWidgetType;
+  }
+
+  public void setUserWidgetType(String userWidgetType) {
+    this.userWidgetType = userWidgetType;
+  }
+
+  public String getMetrics() {
+    return metrics;
+  }
+
+  public void setMetrics(String metrics) {
+    this.metrics = metrics;
+  }
+
+  public Long getTimeCreated() {
+    return timeCreated;
+  }
+
+  public void setTimeCreated(Long timeCreated) {
+    this.timeCreated = timeCreated;
+  }
+
+  public String getAuthor() {
+    return author;
+  }
+
+  public void setAuthor(String author) {
+    this.author = author;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public void setScope(String scope) {
+    this.scope = scope;
+  }
+
+  public String getWidgetValues() {
+    return widgetValues;
+  }
+
+  public void setWidgetValues(String widgetValues) {
+    this.widgetValues = widgetValues;
+  }
+
+  public String getProperties() {
+    return properties;
+  }
+
+  public void setProperties(String properties) {
+    this.properties = properties;
+  }
+
+  public ClusterEntity getClusterEntity() {
+    return clusterEntity;
+  }
+
+  public void setClusterEntity(ClusterEntity clusterEntity) {
+    this.clusterEntity = clusterEntity;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public List<WidgetLayoutUserWidgetEntity> 
getListWidgetLayoutUserWidgetEntity() {
+    return listWidgetLayoutUserWidgetEntity;
+  }
+
+  public void 
setListWidgetLayoutUserWidgetEntity(List<WidgetLayoutUserWidgetEntity> 
listWidgetLayoutUserWidgetEntity) {
+    this.listWidgetLayoutUserWidgetEntity = listWidgetLayoutUserWidgetEntity;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    UserWidgetEntity that = (UserWidgetEntity) o;
+
+    if (id != that.id) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = null != id ? id.hashCode() : 0;
+    return result;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
new file mode 100644
index 0000000..dfce4f4
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutEntity.java
@@ -0,0 +1,130 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.List;
+
+@Entity
+@Table(name = "widget_layout")
+@NamedQueries({
+    @NamedQuery(name = "WidgetLayoutEntity.findAll", query = "SELECT 
widgetLayout FROM WidgetLayoutEntity widgetLayout"),
+    @NamedQuery(name = "WidgetLayoutEntity.findByCluster", query = "SELECT 
widgetLayout FROM WidgetLayoutEntity widgetLayout WHERE widgetLayout.clusterId 
= :clusterId"),
+    @NamedQuery(name = "WidgetLayoutEntity.findBySectionName", query = "SELECT 
widgetLayout FROM WidgetLayoutEntity widgetLayout WHERE 
widgetLayout.sectionName = :sectionName"),
+    })
+public class WidgetLayoutEntity {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "id", nullable = false, updatable = false)
+  private Long id;
+
+  @Column(name = "layout_name", nullable = false, unique = true, length = 255)
+  private String layoutName;
+
+  @Column(name = "section_name", nullable = false, length = 255)
+  private String sectionName;
+
+  @Column(name = "cluster_id", nullable = false)
+  private Long clusterId;
+
+  @ManyToOne
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", 
nullable = false, updatable = false, insertable = false)
+  private ClusterEntity clusterEntity;
+
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widgetLayout")
+  private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getLayoutName() {
+    return layoutName;
+  }
+
+  public void setLayoutName(String layoutName) {
+    this.layoutName = layoutName;
+  }
+
+  public String getSectionName() {
+    return sectionName;
+  }
+
+  public void setSectionName(String sectionName) {
+    this.sectionName = sectionName;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public ClusterEntity getClusterEntity() {
+    return clusterEntity;
+  }
+
+  public void setClusterEntity(ClusterEntity clusterEntity) {
+    this.clusterEntity = clusterEntity;
+  }
+
+  public List<WidgetLayoutUserWidgetEntity> 
getListWidgetLayoutUserWidgetEntity() {
+    return listWidgetLayoutUserWidgetEntity;
+  }
+
+  public void 
setListWidgetLayoutUserWidgetEntity(List<WidgetLayoutUserWidgetEntity> 
listWidgetLayoutUserWidgetEntity) {
+    this.listWidgetLayoutUserWidgetEntity = listWidgetLayoutUserWidgetEntity;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    WidgetLayoutEntity that = (WidgetLayoutEntity) o;
+
+    if (id != that.id) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = null != id ? id.hashCode() : 0;
+    return result;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
new file mode 100644
index 0000000..5de9f89
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.entities;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@IdClass(WidgetLayoutUserWidgetEntityPK.class)
+@Entity
+@Table(name = "widget_layout_user_widget")
+public class WidgetLayoutUserWidgetEntity {
+
+
+  @Id
+  @Column(name = "widget_layout_id", nullable = false, updatable = false, 
insertable = false)
+  private Long widgetLayoutId;
+
+  @Id
+  @Column(name = "user_widget_id", nullable = false, updatable = false, 
insertable = false)
+  private Long userWidgetId;
+
+  @ManyToOne(cascade = { CascadeType.ALL })
+  @JoinColumn(name = "widget_layout_id", referencedColumnName = "id")
+  private WidgetLayoutEntity widgetLayout;
+
+  @ManyToOne(cascade = { CascadeType.ALL })
+  @JoinColumn(name = "user_widget_id", referencedColumnName = "id")
+  private UserWidgetEntity userWidget;
+
+  @Column(name = "widget_order")
+  private Integer widgetOrder;
+
+  public Long getWidgetLayoutId() {
+    return widgetLayoutId;
+  }
+
+  public void setWidgetLayoutId(Long widgetLayoutId) {
+    this.widgetLayoutId = widgetLayoutId;
+  }
+
+  public Long getUserWidgetId() {
+    return userWidgetId;
+  }
+
+  public void setUserWidgetId(Long userWidgetId) {
+    this.userWidgetId = userWidgetId;
+  }
+
+  public WidgetLayoutEntity getWidgetLayout() {
+    return widgetLayout;
+  }
+
+  public void setWidgetLayout(WidgetLayoutEntity widgetLayout) {
+    this.widgetLayout = widgetLayout;
+  }
+
+  public UserWidgetEntity getUserWidget() {
+    return userWidget;
+  }
+
+  public void setUserWidget(UserWidgetEntity userWidget) {
+    this.userWidget = userWidget;
+  }
+
+  public Integer getWidgetOrder() {
+    return widgetOrder;
+  }
+
+  public void setWidgetOrder(Integer widgetOrder) {
+    this.widgetOrder = widgetOrder;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    WidgetLayoutUserWidgetEntity that = (WidgetLayoutUserWidgetEntity) o;
+
+    if (widgetLayout.getId() != that.widgetLayout.getId()) return false;
+    if (userWidget.getId() != that.userWidget.getId()) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = null != widgetLayout ? widgetLayout.hashCode() : 0;
+    result = 31 * result + (userWidget != null ? userWidget.hashCode() : 0);
+    return result;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
new file mode 100644
index 0000000..4fdd977
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+public class WidgetLayoutUserWidgetEntityPK  implements Serializable {
+
+
+  private Long widgetLayoutId;
+
+  @Id
+  @Column(name = "widget_layout_id", nullable = false, updatable = false)
+  public Long getWidgetLayoutId() {
+    return widgetLayoutId;
+  }
+
+  public void setWidgetLayoutId(Long widgetLayoutId) {
+    this.widgetLayoutId = widgetLayoutId;
+  }
+
+  private Long userWidgetId;
+
+  @Id
+  @Column(name = "user_widget_id", nullable = false, updatable = false)
+  public Long getUserWidgetId() {
+    return userWidgetId;
+  }
+
+  public void setUserWidgetId(Long userWidgetId) {
+    this.userWidgetId = userWidgetId;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    WidgetLayoutUserWidgetEntityPK that = (WidgetLayoutUserWidgetEntityPK) o;
+
+    if (widgetLayoutId != that.widgetLayoutId) return false;
+    if (userWidgetId != that.userWidgetId) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = null != widgetLayoutId ? widgetLayoutId.hashCode() : 0;
+    result = 31 * result + (userWidgetId != null ? userWidgetId.hashCode() : 
0);
+    return result;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
index 92f1dac..ba4dd2d 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
@@ -31,6 +31,8 @@ import org.slf4j.LoggerFactory;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
 
 
 /**
@@ -52,6 +54,9 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog 
{
   private static final String CONFIG_GROUP_HOST_MAPPING_TABLE = 
"configgrouphostmapping";
   private static final String KERBEROS_PRINCIPAL_HOST_TABLE = 
"kerberos_principal_host";
   private static final String CLUSTER_HOST_MAPPING_TABLE = 
"ClusterHostMapping";
+  private static final String USER_WIDGET_TABLE = "user_widget";
+  private static final String WIDGET_LAYOUT_TABLE = "widget_layout";
+  private static final String WIDGET_LAYOUT_USER_WIDGET_TABLE = 
"widget_layout_user_widget";
 
   /**
    * {@inheritDoc}
@@ -95,6 +100,7 @@ public class UpgradeCatalog210 extends 
AbstractUpgradeCatalog {
   @Override
   protected void executeDDLUpdates() throws AmbariException, SQLException {
     executeHostsDDLUpdates();
+    executeWidgetDDLUpdates();
   }
 
   /**
@@ -226,6 +232,40 @@ public class UpgradeCatalog210 extends 
AbstractUpgradeCatalog {
     dbAccessor.dropColumn(CLUSTER_HOST_MAPPING_TABLE, "host_name");
   }
 
+  private void executeWidgetDDLUpdates() throws AmbariException, SQLException {
+    List<DBColumnInfo> columns = new ArrayList<DBColumnInfo>();
+
+    columns.add(new DBColumnInfo("id", Long.class,    null,  null, false));
+    columns.add(new DBColumnInfo("user_widget_name", String.class,  255,   
null, false));
+    columns.add(new DBColumnInfo("user_widget_type", String.class,  255,   
null, false));
+    columns.add(new DBColumnInfo("metrics", String.class,  32672,   null, 
true));
+    columns.add(new DBColumnInfo("time_created", Long.class,  255,   null, 
false));
+    columns.add(new DBColumnInfo("author", String.class,  255,   null, true));
+    columns.add(new DBColumnInfo("description", String.class,  255,   null, 
true));
+    columns.add(new DBColumnInfo("display_name", String.class,  255,   null, 
false));
+    columns.add(new DBColumnInfo("scope", String.class,  255,   null, true));
+    columns.add(new DBColumnInfo("widget_values", String.class,  255,   null, 
true));
+    columns.add(new DBColumnInfo("properties", String.class,  255,   null, 
true));
+    columns.add(new DBColumnInfo("cluster_id", Long.class,  255,   null, 
false));
+    dbAccessor.createTable(USER_WIDGET_TABLE, columns, "id");
+
+    columns = new ArrayList<DBColumnInfo>();
+    columns.add(new DBColumnInfo("id", Long.class,    null,  null, false));
+    columns.add(new DBColumnInfo("layout_name", String.class,  255,   null, 
false));
+    columns.add(new DBColumnInfo("section_name", String.class,  255,   null, 
false));
+    columns.add(new DBColumnInfo("cluster_id", Long.class,  255,   null, 
false));
+    dbAccessor.createTable(WIDGET_LAYOUT_TABLE, columns, "id");
+    dbAccessor.executeQuery("ALTER TABLE widget_layout ADD CONSTRAINT 
UQ_widget_layout UNIQUE (layout_name, section_name)");
+
+    columns = new ArrayList<DBColumnInfo>();
+    columns.add(new DBColumnInfo("widget_layout_id", Long.class,    null,  
null, false));
+    columns.add(new DBColumnInfo("user_widget_id", Long.class,    null,  null, 
false));
+    columns.add(new DBColumnInfo("widget_order", Integer.class,    null,  
null, false));
+    dbAccessor.createTable(WIDGET_LAYOUT_USER_WIDGET_TABLE, columns, 
"widget_layout_id", "user_widget_id");
+    dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, 
"FK_widget_layout_id", "widget_layout_id", "widget_layout", "id", true, false);
+    dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, 
"FK_user_widget_id", "user_widget_id", "user_widget", "id", true, false);
+  }
+
   // ----- UpgradeCatalog ----------------------------------------------------
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index c63be06..a9cf3e8 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -538,6 +538,37 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
+CREATE TABLE ambari.user_widget (
+  id BIGINT NOT NULL,
+  user_widget_name VARCHAR(255) NOT NULL,
+  user_widget_type VARCHAR(255) NOT NULL,
+  metrics LONGTEXT,
+  time_created TIMESTAMP DEFAULT NOW(),
+  author VARCHAR(255),
+  description VARCHAR(255),
+  display_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255),
+  widget_values VARCHAR(255),
+  properties VARCHAR(255),
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE ambari.widget_layout (
+  id BIGINT NOT NULL,
+  layout_name VARCHAR(255) NOT NULL,
+  section_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE ambari.widget_layout_user_widget (
+  widget_layout_id BIGINT NOT NULL,
+  user_widget_id BIGINT NOT NULL,
+  widget_order smallint,
+  PRIMARY KEY(widget_layout_id, user_widget_id)
+);
+
 CREATE TABLE artifact (
   artifact_name VARCHAR(255) NOT NULL,
   foreign_keys VARCHAR(255) NOT NULL,
@@ -557,6 +588,7 @@ ALTER TABLE serviceconfig ADD CONSTRAINT 
UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id 
UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE 
(display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE 
(stack, version);
+ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, 
section_name);
 
 -- altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) 
REFERENCES groups (group_id);
@@ -625,6 +657,8 @@ ALTER TABLE adminprivilege ADD CONSTRAINT 
FK_privilege_principal_id FOREIGN KEY
 ALTER TABLE users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY 
(principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY 
(principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY 
(resource_id) REFERENCES adminresource(resource_id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id 
FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN 
KEY (user_widget_id) REFERENCES user_widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 307afbe..13e8939 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -526,6 +526,37 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
+CREATE TABLE ambari.user_widget (
+  id NUMBER(19) NOT NULL,
+  user_widget_name VARCHAR2(255) NOT NULL,
+  user_widget_type VARCHAR2(255) NOT NULL,
+  metrics CLOB,
+  time_created TIMESTAMP DEFAULT NOW(),
+  author VARCHAR2(255),
+  description VARCHAR2(255),
+  display_name VARCHAR2(255) NOT NULL,
+  scope VARCHAR2(255),
+  widget_values VARCHAR2(255),
+  properties VARCHAR2(255),
+  cluster_id NUMBER(19) NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE ambari.widget_layout (
+  id NUMBER(19) NOT NULL,
+  layout_name VARCHAR2(255) NOT NULL,
+  section_name VARCHAR2(255) NOT NULL,
+  cluster_id NUMBER(19) NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE ambari.widget_layout_user_widget (
+  widget_layout_id NUMBER(19) NOT NULL,
+  user_widget_id NUMBER(19) NOT NULL,
+  widget_order smallint,
+  PRIMARY KEY(widget_layout_id, user_widget_id)
+);
+
 CREATE TABLE artifact (
   artifact_name VARCHAR2(255) NOT NULL,
   foreign_keys VARCHAR2(255) NOT NULL,
@@ -545,6 +576,7 @@ ALTER TABLE serviceconfig ADD CONSTRAINT 
UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id 
UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE 
(display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE 
(stack, version);
+ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, 
section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) 
REFERENCES groups (group_id);
@@ -613,6 +645,8 @@ ALTER TABLE adminprivilege ADD CONSTRAINT 
FK_privilege_principal_id FOREIGN KEY
 ALTER TABLE users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY 
(principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY 
(principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY 
(resource_id) REFERENCES adminresource(resource_id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id 
FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN 
KEY (user_widget_id) REFERENCES user_widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 38e95ae..cd4427f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -531,6 +531,37 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
+CREATE TABLE user_widget (
+  id BIGINT NOT NULL,
+  user_widget_name VARCHAR(255) NOT NULL,
+  user_widget_type VARCHAR(255) NOT NULL,
+  metrics TEXT,
+  time_created TIMESTAMP DEFAULT NOW(),
+  author VARCHAR(255),
+  description VARCHAR(255),
+  display_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255),
+  widget_values VARCHAR(255),
+  properties VARCHAR(255),
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE widget_layout (
+  id BIGINT NOT NULL,
+  layout_name VARCHAR(255) NOT NULL,
+  section_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+
+CREATE TABLE widget_layout_user_widget (
+  widget_layout_id BIGINT NOT NULL,
+  user_widget_id BIGINT NOT NULL,
+  widget_order smallint,
+  PRIMARY KEY(widget_layout_id, user_widget_id)
+);
+
 CREATE TABLE artifact (
   artifact_name VARCHAR(255) NOT NULL,
   artifact_data TEXT NOT NULL,
@@ -547,6 +578,7 @@ ALTER TABLE serviceconfig ADD CONSTRAINT 
UQ_scv_service_version UNIQUE (cluster_
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id 
UNIQUE (permission_name, resource_type_id);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE 
(display_name);
 ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE 
(stack, version);
+ALTER TABLE widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE (layout_name, 
section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) 
REFERENCES groups (group_id);
@@ -615,6 +647,8 @@ ALTER TABLE serviceconfigmapping ADD CONSTRAINT FK_scvm_scv 
FOREIGN KEY (service
 ALTER TABLE serviceconfigmapping ADD CONSTRAINT FK_scvm_config FOREIGN KEY 
(config_id) REFERENCES clusterconfig(config_id);
 ALTER TABLE serviceconfighosts ADD CONSTRAINT  FK_scvhosts_scv FOREIGN KEY 
(service_config_id) REFERENCES serviceconfig(service_config_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY 
(resource_id) REFERENCES adminresource(resource_id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id 
FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN 
KEY (user_widget_id) REFERENCES user_widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 2e88853..9fe9cd7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -606,6 +606,40 @@ CREATE TABLE ambari.artifact (
   PRIMARY KEY (artifact_name, foreign_keys));
 GRANT ALL PRIVILEGES ON TABLE ambari.artifact TO :username;
 
+CREATE TABLE ambari.user_widget (
+  id BIGINT NOT NULL,
+  user_widget_name VARCHAR(255) NOT NULL,
+  user_widget_type VARCHAR(255) NOT NULL,
+  metrics TEXT,
+  time_created TIMESTAMP DEFAULT NOW(),
+  author VARCHAR(255),
+  description VARCHAR(255),
+  display_name VARCHAR(255) NOT NULL,
+  scope VARCHAR(255),
+  widget_values VARCHAR(255),
+  properties VARCHAR(255),
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+GRANT ALL PRIVILEGES ON TABLE ambari.user_widget TO :username;
+
+CREATE TABLE ambari.widget_layout (
+  id BIGINT NOT NULL,
+  layout_name VARCHAR(255) NOT NULL,
+  section_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  PRIMARY KEY(id)
+);
+GRANT ALL PRIVILEGES ON TABLE ambari.widget_layout TO :username;
+
+CREATE TABLE ambari.widget_layout_user_widget (
+  widget_layout_id BIGINT NOT NULL,
+  user_widget_id BIGINT NOT NULL,
+  widget_order smallint,
+  PRIMARY KEY(widget_layout_id, user_widget_id)
+);
+GRANT ALL PRIVILEGES ON TABLE ambari.widget_layout_user_widget TO :username;
+
 --------altering tables by creating unique constraints----------
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT UQ_config_type_tag UNIQUE 
(cluster_id, type_name, version_tag);
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT UQ_config_type_version UNIQUE 
(cluster_id, type_name, version);
@@ -616,6 +650,7 @@ ALTER TABLE ambari.serviceconfig ADD CONSTRAINT 
UQ_scv_service_version UNIQUE (c
 ALTER TABLE ambari.adminpermission ADD CONSTRAINT 
UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_display_name 
UNIQUE (display_name);
 ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_stack_version 
UNIQUE (stack, version);
+ALTER TABLE ambari.widget_layout ADD CONSTRAINT UQ_widget_layout UNIQUE 
(layout_name, section_name);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE ambari.members ADD CONSTRAINT FK_members_group_id FOREIGN KEY 
(group_id) REFERENCES ambari.groups (group_id);
@@ -684,6 +719,8 @@ ALTER TABLE ambari.adminprivilege ADD CONSTRAINT 
FK_privilege_principal_id FOREI
 ALTER TABLE ambari.users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY 
(principal_id) REFERENCES ambari.adminprincipal(principal_id);
 ALTER TABLE ambari.groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY 
(principal_id) REFERENCES ambari.adminprincipal(principal_id);
 ALTER TABLE ambari.clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY 
(resource_id) REFERENCES ambari.adminresource(resource_id);
+ALTER TABLE ambari.widget_layout_user_widget ADD CONSTRAINT 
FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES 
ambari.widget_layout(id);
+ALTER TABLE ambari.widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id 
FOREIGN KEY (user_widget_id) REFERENCES ambari.user_widget(id);
 
 -- Kerberos
 CREATE TABLE ambari.kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml 
b/ambari-server/src/main/resources/META-INF/persistence.xml
index 8c0d85f..723fbc0 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -70,6 +70,7 @@
     <class>org.apache.ambari.server.orm.entities.UpgradeGroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeItemEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>
+    <class>org.apache.ambari.server.orm.entities.UserWidgetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewInstanceDataEntity</class>
@@ -77,6 +78,8 @@
     
<class>org.apache.ambari.server.orm.entities.ViewInstancePropertyEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewParameterEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewResourceEntity</class>
+    <class>org.apache.ambari.server.orm.entities.WidgetLayoutEntity</class>
+    
<class>org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ArtifactEntity</class>
 
     <properties>      

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UserWidgetDAOTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UserWidgetDAOTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UserWidgetDAOTest.java
new file mode 100644
index 0000000..f86dde8
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UserWidgetDAOTest.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.dao;
+
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.orm.entities.UserWidgetEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * UserWidgetDAO unit tests.
+ */
+public class UserWidgetDAOTest {
+
+  private static Injector injector;
+  private UserWidgetDAO userWidgetDAO;
+  OrmTestHelper helper;
+  Long clusterId;
+
+
+  @Before
+  public void before() {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    userWidgetDAO = injector.getInstance(UserWidgetDAO.class);
+    injector.getInstance(GuiceJpaInitializer.class);
+    helper = injector.getInstance(OrmTestHelper.class);
+    clusterId = helper.createCluster();
+  }
+
+  private void createRecords() {
+    for (int i=0; i<3; i++) {
+      UserWidgetEntity userWidgetEntity = new UserWidgetEntity();
+      userWidgetEntity.setDisplayName("display name" + i);
+      userWidgetEntity.setAuthor("author");
+      userWidgetEntity.setClusterId(clusterId);
+      userWidgetEntity.setMetrics("metrics");
+      userWidgetEntity.setDescription("description");
+      userWidgetEntity.setProperties("{\"warning_threshold\": 
0.5,\"error_threshold\": 0.7 }");
+      userWidgetEntity.setScope("CLUSTER");
+      userWidgetEntity.setUserWidgetName("widget" + i);
+      userWidgetEntity.setUserWidgetType("GAUGE");
+      userWidgetEntity.setWidgetValues("${`jvmMemoryHeapUsed + 
jvmMemoryHeapMax`}");
+      final WidgetLayoutEntity widgetLayoutEntity = new WidgetLayoutEntity();
+      widgetLayoutEntity.setClusterId(clusterId);
+      widgetLayoutEntity.setLayoutName("layout name" + i);
+      widgetLayoutEntity.setSectionName("section" + i%2);
+      final WidgetLayoutUserWidgetEntity widgetLayoutUserWidget = new 
WidgetLayoutUserWidgetEntity();
+      widgetLayoutUserWidget.setUserWidget(userWidgetEntity);
+      widgetLayoutUserWidget.setWidgetLayout(widgetLayoutEntity);
+      widgetLayoutUserWidget.setWidgetOrder(0);
+
+      List<WidgetLayoutUserWidgetEntity> widgetLayoutUserWidgetEntityList = 
new LinkedList<WidgetLayoutUserWidgetEntity>();
+      widgetLayoutUserWidgetEntityList.add(widgetLayoutUserWidget);
+
+      
userWidgetEntity.setListWidgetLayoutUserWidgetEntity(widgetLayoutUserWidgetEntityList);
+      userWidgetDAO.create(userWidgetEntity);
+    }
+  }
+
+  @Test
+  public void testFindByCluster() {
+    createRecords();
+    Assert.assertEquals(0, userWidgetDAO.findByCluster(99999).size());
+    Assert.assertEquals(3, userWidgetDAO.findByCluster(clusterId).size());
+  }
+
+  @Test
+  public void testFindBySectionName() {
+    createRecords();
+    Assert.assertEquals(0, userWidgetDAO.findBySectionName("non 
existing").size());
+    Assert.assertEquals(2, userWidgetDAO.findBySectionName("section0").size());
+    Assert.assertEquals(1, userWidgetDAO.findBySectionName("section1").size());
+  }
+
+  @Test
+  public void testFindAll() {
+    createRecords();
+    Assert.assertEquals(3, userWidgetDAO.findAll().size());
+  }
+
+  @After
+  public void after() {
+    injector.getInstance(PersistService.class).stop();
+    injector = null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAOTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAOTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAOTest.java
new file mode 100644
index 0000000..3d83399
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/WidgetLayoutDAOTest.java
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ambari.server.orm.dao;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.entities.UserWidgetEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
+import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * WidgetLayoutDAO unit tests.
+ */
+public class WidgetLayoutDAOTest {
+
+  private static Injector injector;
+  private WidgetLayoutDAO widgetLayoutDAO;
+  OrmTestHelper helper;
+  Long clusterId;
+
+
+  @Before
+  public void before() {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    widgetLayoutDAO = injector.getInstance(WidgetLayoutDAO.class);
+    injector.getInstance(GuiceJpaInitializer.class);
+    helper = injector.getInstance(OrmTestHelper.class);
+    clusterId = helper.createCluster();
+  }
+
+  private void createRecords() {
+
+    WidgetLayoutEntity widgetLayoutEntity = new WidgetLayoutEntity();
+    widgetLayoutEntity.setClusterId(clusterId);
+    widgetLayoutEntity.setLayoutName("layout name0");
+    widgetLayoutEntity.setSectionName("section0");
+
+    WidgetLayoutEntity widgetLayoutEntity2 = new WidgetLayoutEntity();
+    widgetLayoutEntity2.setClusterId(clusterId);
+    widgetLayoutEntity2.setLayoutName("layout name1");
+    widgetLayoutEntity2.setSectionName("section1");
+
+    List<WidgetLayoutUserWidgetEntity> widgetLayoutUserWidgetEntityList = new 
LinkedList<WidgetLayoutUserWidgetEntity>();
+
+    for (int i=0; i<3; i++) {
+      UserWidgetEntity userWidgetEntity = new UserWidgetEntity();
+      userWidgetEntity.setDisplayName("display name" + i);
+      userWidgetEntity.setAuthor("author");
+      userWidgetEntity.setClusterId(clusterId);
+      userWidgetEntity.setMetrics("metrics");
+      userWidgetEntity.setDescription("description");
+      userWidgetEntity.setProperties("{\"warning_threshold\": 
0.5,\"error_threshold\": 0.7 }");
+      userWidgetEntity.setScope("CLUSTER");
+      userWidgetEntity.setUserWidgetName("widget" + i);
+      userWidgetEntity.setUserWidgetType("GAUGE");
+      userWidgetEntity.setWidgetValues("${`jvmMemoryHeapUsed + 
jvmMemoryHeapMax`}");
+
+      WidgetLayoutUserWidgetEntity widgetLayoutUserWidget = new 
WidgetLayoutUserWidgetEntity();
+      widgetLayoutUserWidget.setUserWidget(userWidgetEntity);
+      widgetLayoutUserWidget.setWidgetLayout(widgetLayoutEntity);
+      widgetLayoutUserWidget.setWidgetOrder(0);
+      widgetLayoutUserWidgetEntityList.add(widgetLayoutUserWidget);
+    }
+
+    
widgetLayoutEntity.setListWidgetLayoutUserWidgetEntity(widgetLayoutUserWidgetEntityList);
+    widgetLayoutDAO.create(widgetLayoutEntity);
+    widgetLayoutDAO.create(widgetLayoutEntity2);
+
+  }
+
+  @Test
+  public void testFindByCluster() {
+    createRecords();
+    Assert.assertEquals(0, widgetLayoutDAO.findByCluster(99999).size());
+    Assert.assertEquals(2, widgetLayoutDAO.findByCluster(clusterId).size());
+  }
+
+  @Test
+  public void testFindBySectionName() {
+    createRecords();
+    Assert.assertEquals(0, widgetLayoutDAO.findBySectionName("non 
existing").size());
+    List<WidgetLayoutEntity> widgetLayoutEntityList1 =  
widgetLayoutDAO.findBySectionName("section0");
+    List<WidgetLayoutEntity> widgetLayoutEntityList2 =  
widgetLayoutDAO.findBySectionName("section1");
+
+    Assert.assertEquals(1, widgetLayoutEntityList1.size());
+    Assert.assertEquals(1, widgetLayoutEntityList2.size());
+    Assert.assertEquals(3, 
widgetLayoutEntityList1.get(0).getListWidgetLayoutUserWidgetEntity().size());
+  }
+
+  @Test
+  public void testFindAll() {
+    createRecords();
+    Assert.assertEquals(2, widgetLayoutDAO.findAll().size());
+  }
+
+  @After
+  public void after() {
+    injector.getInstance(PersistService.class).stop();
+    injector = null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/308a618f/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
index 0d7cd08..07b8410 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
@@ -42,14 +42,26 @@ import javax.persistence.EntityManager;
 import java.lang.reflect.Field;
 import java.sql.Connection;
 import java.sql.ResultSet;
+import java.util.List;
 
-import static org.easymock.EasyMock.*;
 import static org.easymock.EasyMock.capture;
 
+import static junit.framework.Assert.assertEquals;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+
 /**
  * {@link org.apache.ambari.server.upgrade.UpgradeCatalog210} unit tests.
  */
 public class UpgradeCatalog210Test {
+  private final String CLUSTER_NAME = "c1";
+  private final String HOST_NAME = "h1";
+  private final String DESIRED_STACK_VERSION = 
"{\"stackName\":\"HDP\",\"stackVersion\":\"2.0.6\"}";
 
   private Injector injector;
   private Provider<EntityManager> entityManagerProvider = 
createStrictMock(Provider.class);
@@ -90,6 +102,22 @@ public class UpgradeCatalog210Test {
     // Add columns and alter table section
     dbAccessor.addColumn(eq("hosts"), capture(hostsColumnCapture));
 
+    Capture<List<DBColumnInfo>> userWidgetColumnsCapture = new 
Capture<List<DBColumnInfo>>();
+    Capture<List<DBColumnInfo>> widgetLayoutColumnsCapture = new 
Capture<List<DBColumnInfo>>();
+    Capture<List<DBColumnInfo>> widgetLayoutUserWidgetColumnsCapture = new 
Capture<List<DBColumnInfo>>();
+
+    // User Widget
+    dbAccessor.createTable(eq("user_widget"),
+        capture(userWidgetColumnsCapture), eq("id"));
+
+    // Widget Layout
+    dbAccessor.createTable(eq("widget_layout"),
+            capture(widgetLayoutColumnsCapture), eq("id"));
+
+    // Widget Layout User Widget
+    dbAccessor.createTable(eq("widget_layout_user_widget"),
+            capture(widgetLayoutUserWidgetColumnsCapture), 
eq("widget_layout_id"), eq("user_widget_id"));
+
     // Replay section
     replay(dbAccessor, configuration, resultSet);
     replay(hostDao, mockHost);
@@ -105,6 +133,12 @@ public class UpgradeCatalog210Test {
 
     // Verification section
     verifyHosts(hostsColumnCapture);
+
+
+    // Verify widget tables
+    assertEquals(12, userWidgetColumnsCapture.getValue().size());
+    assertEquals(4, widgetLayoutColumnsCapture.getValue().size());
+    assertEquals(3, widgetLayoutUserWidgetColumnsCapture.getValue().size());
   }
 
   private void verifyHosts(Capture<DBAccessor.DBColumnInfo> 
hostsColumnCapture) {

Reply via email to