Committing patch for RAVE-1075

git-svn-id: https://svn.apache.org/repos/asf/rave/trunk@1543653 
13f79535-47bb-0310-9956-ffa450edef68


Project: http://git-wip-us.apache.org/repos/asf/rave/repo
Commit: http://git-wip-us.apache.org/repos/asf/rave/commit/3909e6e0
Tree: http://git-wip-us.apache.org/repos/asf/rave/tree/3909e6e0
Diff: http://git-wip-us.apache.org/repos/asf/rave/diff/3909e6e0

Branch: refs/heads/angular
Commit: 3909e6e06888d5158d032473c1a487c210aa23d5
Parents: 23b232c
Author: Matthew B. Franklin <[email protected]>
Authored: Tue Nov 19 23:55:21 2013 +0000
Committer: Matthew B. Franklin <[email protected]>
Committed: Tue Nov 19 23:55:21 2013 +0000

----------------------------------------------------------------------
 .../main/java/org/apache/rave/model/Widget.java | 17 +++++
 .../java/org/apache/rave/rest/model/Widget.java | 12 ++++
 .../rave/portal/model/impl/WidgetImpl.java      | 10 +++
 .../rave/rest/impl/DefaultWidgetsResource.java  |  1 +
 .../rest/impl/DefaultWidgetsResourceTest.java   |  6 ++
 .../org/apache/rave/portal/model/JpaPage.java   |  2 +-
 .../org/apache/rave/portal/model/JpaWidget.java | 69 ++++++++++++------
 .../model/conversion/JpaWidgetConverter.java    |  1 +
 .../repository/impl/JpaWidgetRepository.java    | 36 +++++++---
 .../conversion/JpaWidgetConverterTest.java      |  3 +
 .../impl/JpaWidgetRepositoryTest.java           | 73 +++++++++++++++++++-
 .../rave-jpa/src/test/resources/test_data.sql   |  4 +-
 .../conversion/impl/MongoDbWidgetConverter.java |  1 +
 .../impl/MongoDbWidgetConverterTest.java        |  6 ++
 .../OpenSocialWidgetWrapperRenderer.java        |  7 +-
 .../renderer/OpenSocialWidgetRendererTest.java  | 11 ++-
 .../web/renderer/W3cRegionWidgetRenderer.java   | 69 ++++++++++++++++++
 .../web/renderer/W3cWidgetWrapperRenderer.java  |  7 +-
 18 files changed, 292 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-core-api/src/main/java/org/apache/rave/model/Widget.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-core-api/src/main/java/org/apache/rave/model/Widget.java 
b/rave-components/rave-core-api/src/main/java/org/apache/rave/model/Widget.java
index 4022007..585593a 100644
--- 
a/rave-components/rave-core-api/src/main/java/org/apache/rave/model/Widget.java
+++ 
b/rave-components/rave-core-api/src/main/java/org/apache/rave/model/Widget.java
@@ -21,6 +21,7 @@ package org.apache.rave.model;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlTransient;
 import java.util.List;
+import java.util.Map;
 
 @XmlTransient
 public interface Widget {
@@ -106,4 +107,20 @@ public interface Widget {
     boolean isFeatured();
 
     void setFeatured(boolean featured);
+
+    /**
+     * Generic property bag for extension of the widget object.
+     *
+     * Rave makes no attempt to understand the shape of properties in the bag.
+     *
+     * @return a valid Map of String to JSON Serializable Object.
+     */
+    Map<String, Object> getProperties();
+
+    /**
+     * Overrides the current properties with a new set.
+     *
+     * @param properties a non-null map of string to JSON serializable objects
+     */
+    void setProperties(Map<String, Object> properties);
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-core-api/src/main/java/org/apache/rave/rest/model/Widget.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-core-api/src/main/java/org/apache/rave/rest/model/Widget.java
 
b/rave-components/rave-core-api/src/main/java/org/apache/rave/rest/model/Widget.java
index 68d085d..aef9162 100644
--- 
a/rave-components/rave-core-api/src/main/java/org/apache/rave/rest/model/Widget.java
+++ 
b/rave-components/rave-core-api/src/main/java/org/apache/rave/rest/model/Widget.java
@@ -21,6 +21,7 @@ package org.apache.rave.rest.model;
 import org.apache.rave.model.WidgetStatus;
 
 import javax.xml.bind.annotation.*;
+import java.util.Map;
 
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "Widget", propOrder = {
@@ -51,6 +52,8 @@ public class Widget {
     private String description;
     @XmlElement(name = "status")
     private WidgetStatus status;
+    @XmlElement(name = "properties")
+    private Map<String, Object> properties;
     @XmlElement(name = "disable")
     private boolean disable;
     @XmlElement(name = "disabledMessage")
@@ -75,6 +78,7 @@ public class Widget {
         this.disable = base.isDisableRendering();
         this.disabledMessage = base.getDisableRenderingMessage();
         this.featured = base.isFeatured();
+        this.properties = base.getProperties();
     }
 
 
@@ -166,6 +170,14 @@ public class Widget {
         this.status = status;
     }
 
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
     public boolean isDisable() {
         return disable;
     }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/impl/WidgetImpl.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/impl/WidgetImpl.java
 
b/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/impl/WidgetImpl.java
index 8918956..fbfdf81 100644
--- 
a/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/impl/WidgetImpl.java
+++ 
b/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/impl/WidgetImpl.java
@@ -22,6 +22,7 @@ import org.apache.rave.model.*;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 public class WidgetImpl implements Widget {
     private String id;
@@ -43,6 +44,7 @@ public class WidgetImpl implements Widget {
     private List<WidgetTag> tags = new ArrayList<WidgetTag>();
     private List<Category> categories = new ArrayList<Category>();
     private boolean featured;
+    private Map<String, Object> properties;
 
     public WidgetImpl() {}
 
@@ -207,6 +209,14 @@ public class WidgetImpl implements Widget {
         this.featured = featured;
     }
 
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-core/src/main/java/org/apache/rave/rest/impl/DefaultWidgetsResource.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-core/src/main/java/org/apache/rave/rest/impl/DefaultWidgetsResource.java
 
b/rave-components/rave-core/src/main/java/org/apache/rave/rest/impl/DefaultWidgetsResource.java
index 00e0bc8..f07075f 100644
--- 
a/rave-components/rave-core/src/main/java/org/apache/rave/rest/impl/DefaultWidgetsResource.java
+++ 
b/rave-components/rave-core/src/main/java/org/apache/rave/rest/impl/DefaultWidgetsResource.java
@@ -81,5 +81,6 @@ public class DefaultWidgetsResource implements 
WidgetsResource {
         fromDb.setDisableRendering(widget.isDisable());
         fromDb.setDisableRenderingMessage(widget.getDisabledMessage());
         fromDb.setFeatured(widget.isFeatured());
+        fromDb.setProperties(widget.getProperties());
     }
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-core/src/test/java/org/apache/rave/rest/impl/DefaultWidgetsResourceTest.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-core/src/test/java/org/apache/rave/rest/impl/DefaultWidgetsResourceTest.java
 
b/rave-components/rave-core/src/test/java/org/apache/rave/rest/impl/DefaultWidgetsResourceTest.java
index 7141cf6..24c6994 100644
--- 
a/rave-components/rave-core/src/test/java/org/apache/rave/rest/impl/DefaultWidgetsResourceTest.java
+++ 
b/rave-components/rave-core/src/test/java/org/apache/rave/rest/impl/DefaultWidgetsResourceTest.java
@@ -20,6 +20,7 @@ package org.apache.rave.rest.impl;
 
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.apache.rave.model.Widget;
 import org.apache.rave.model.WidgetStatus;
 import org.apache.rave.portal.model.impl.WidgetImpl;
@@ -31,6 +32,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
+import java.util.Map;
 
 import static org.easymock.EasyMock.*;
 import static org.hamcrest.CoreMatchers.*;
@@ -60,6 +62,9 @@ public class DefaultWidgetsResourceTest {
         w1.setDisableRendering(true);
         w1.setDisableRenderingMessage("");
         w1.setFeatured(true);
+        Map<String, Object> properties = Maps.newHashMap();
+        properties.put("foo", "bar");
+        w1.setProperties(properties);
         w2 = new WidgetImpl("2", "http://example.com/2";);
         w3 = new WidgetImpl("1", "http://example.com/2";);
     }
@@ -130,5 +135,6 @@ public class DefaultWidgetsResourceTest {
         assertThat(widget.isDisable(), 
is(equalTo(source.isDisableRendering())));
         assertThat(widget.getDisabledMessage(), 
is(equalTo(source.getDisableRenderingMessage())));
         assertThat(widget.isFeatured(), is(equalTo(source.isFeatured())));
+        assertThat((String)widget.getProperties().get("foo"), 
is(equalTo("bar")));
     }
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaPage.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaPage.java
 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaPage.java
index 462dd8c..8c7e144 100644
--- 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaPage.java
+++ 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaPage.java
@@ -54,7 +54,7 @@ import java.util.*;
 })
 @Access(AccessType.FIELD)
 public class JpaPage implements BasicEntity, Serializable, Page {
-    private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 2L;
 
     public static final String DELETE_BY_USER_ID_AND_PAGE_TYPE = 
"JpaPage.deleteByUserIdAndPageType";
     public static final String USER_HAS_PERSON_PAGE = "JpaPage.hasPersonPage";

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaWidget.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaWidget.java
 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaWidget.java
index da0c0a5..2d7fc18 100644
--- 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaWidget.java
+++ 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/JpaWidget.java
@@ -19,37 +19,19 @@
 
 package org.apache.rave.portal.model;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.apache.rave.model.*;
 import org.apache.rave.portal.model.conversion.ConvertingListProxyFactory;
+import org.apache.rave.util.JsonUtils;
 
-import javax.persistence.Access;
-import javax.persistence.AccessType;
-import javax.persistence.Basic;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.Lob;
-import javax.persistence.ManyToMany;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.OrderBy;
-import javax.persistence.Table;
-import javax.persistence.TableGenerator;
+import javax.persistence.*;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A widget
@@ -84,7 +66,7 @@ import java.util.List;
         @NamedQuery(name = JpaWidget.WIDGET_UNASSIGN_OWNER, query = "UPDATE 
JpaWidget w SET w.ownerId = null " + JpaWidget.WHERE_CLAUSE_OWNER )
 })
 public class JpaWidget implements BasicEntity, Serializable, Widget {
-    private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 2L;
 
     public static final String PARAM_SEARCH_TERM = "searchTerm";
     public static final String PARAM_STATUS = "widgetStatus";
@@ -218,6 +200,15 @@ public class JpaWidget implements BasicEntity, 
Serializable, Widget {
     @Column(name = "featured", columnDefinition = "boolean default false")
     private boolean featured;
 
+    @Lob @JsonIgnore
+    @Column(name = "serialized_data")
+    private String serializedData;
+
+    //It will be the responsibility of the repository to ensure that this
+    //property is set when the page is retrieved from the database
+    @Transient
+    private Map<String, Object> properties;
+
     public JpaWidget() {
     }
 
@@ -465,6 +456,38 @@ public class JpaWidget implements BasicEntity, 
Serializable, Widget {
     }
 
     @Override
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    @Override
+    public void setProperties(Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
+    public String getSerializedData() {
+        return serializedData;
+    }
+
+    public void setSerializedData(String serializedData) {
+        this.serializedData = serializedData;
+    }
+
+    public void serializeData() {
+        Map<String, Object> properties = this.getProperties();
+        if(properties != null) {
+            serializedData = JsonUtils.stringify(properties);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void deserializeData() {
+        if(serializedData != null) {
+            this.setProperties(JsonUtils.parse(serializedData, Map.class));
+        }
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (obj == null) {
             return false;

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/conversion/JpaWidgetConverter.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/conversion/JpaWidgetConverter.java
 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/conversion/JpaWidgetConverter.java
index e4d7a0b..25ff1ab 100644
--- 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/conversion/JpaWidgetConverter.java
+++ 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/model/conversion/JpaWidgetConverter.java
@@ -73,5 +73,6 @@ public class JpaWidgetConverter implements 
ModelConverter<Widget, JpaWidget> {
         converted.setTags(source.getTags());
         converted.setCategories(source.getCategories());
         converted.setFeatured(source.isFeatured());
+        converted.setProperties(source.getProperties());
     }
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
index 8505634..426c172 100644
--- 
a/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
+++ 
b/rave-components/rave-jpa/src/main/java/org/apache/rave/portal/repository/impl/JpaWidgetRepository.java
@@ -93,13 +93,13 @@ public class JpaWidgetRepository implements 
WidgetRepository {
     public List<Widget> getAll() {
         log.warn("Requesting potentially large resultset of Widget. No 
pagesize set.");
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.GET_ALL, JpaWidget.class);
-        return CollectionUtils.<Widget>toBaseTypedList(query.getResultList());
+        return expandProperties(query.getResultList());
     }
 
     @Override
     public List<Widget> getLimitedList(int offset, int pageSize) {
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.GET_ALL, JpaWidget.class);
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(query, offset, 
pageSize));
+        return expandProperties(getPagedResultList(query, offset, pageSize));
     }
 
     @Override
@@ -114,7 +114,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.WIDGET_GET_BY_FREE_TEXT,
                 JpaWidget.class);
         setFreeTextSearchTerm(query, searchTerm);
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(query, offset, 
pageSize));
+        return expandProperties(getPagedResultList(query, offset, pageSize));
     }
 
     @Override
@@ -130,7 +130,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.WIDGET_GET_BY_STATUS,
                 JpaWidget.class);
         query.setParameter(JpaWidget.PARAM_STATUS, widgetStatus);
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(query, offset, 
pageSize));
+        return expandProperties(getPagedResultList(query, offset, pageSize));
     }
 
     @Override
@@ -150,7 +150,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         query.where(getStatusAndTypeAndFreeTextPredicates(cb, widgetType, 
widgetStatus, type, searchTerm));
         query.orderBy(getOrderByTitleAsc(cb, widgetType));
 
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(manager.createQuery(query),
 offset, pageSize));
+        return expandProperties(getPagedResultList(manager.createQuery(query), 
offset, pageSize));
     }
 
     @Override
@@ -169,7 +169,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
     public List<Widget> getByOwner(User owner, int offset, int pageSize) {
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.WIDGET_GET_BY_OWNER, JpaWidget.class);
         query.setParameter(JpaWidget.PARAM_OWNER, owner.getId());
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(query, offset, 
pageSize));
+        return expandProperties(getPagedResultList(query, offset, pageSize));
     }
 
     @Override
@@ -190,7 +190,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         // url is a unique field, so no paging needed
         query.setParameter(JpaWidget.PARAM_URL, widgetUrl);
         final List<JpaWidget> resultList = query.getResultList();
-        return getSingleResult(resultList);
+        return expandProperties(getSingleResult(resultList));
     }
 
     @Override
@@ -300,7 +300,7 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         Tag tag = tagRepository.getByKeyword(tagKeyword);
         TypedQuery<JpaWidget> query = 
manager.createNamedQuery(JpaWidget.WIDGET_GET_BY_TAG, JpaWidget.class);
         query.setParameter(JpaWidget.PARAM_TAG_ID, tag == null ? null : 
Long.parseLong(tag.getId()));
-        return 
CollectionUtils.<Widget>toBaseTypedList(getPagedResultList(query, offset, 
pageSize));
+        return expandProperties(getPagedResultList(query, offset, pageSize));
     }
 
     @Override
@@ -329,12 +329,14 @@ public class JpaWidgetRepository implements 
WidgetRepository {
 
     @Override
     public Widget get(String id) {
-        return manager.find(JpaWidget.class, Long.parseLong(id));
+        return expandProperties(manager.find(JpaWidget.class, 
Long.parseLong(id)));
     }
 
     @Override
     public Widget save(Widget item) {
-        return saveOrUpdate(item.getId(), manager, converter.convert(item));
+        JpaWidget converted = converter.convert(item);
+        converted.serializeData();
+        return expandProperties(saveOrUpdate(item.getId(), manager, 
converted));
     }
 
     @Override
@@ -514,4 +516,18 @@ public class JpaWidgetRepository implements 
WidgetRepository {
         query.setParameter("userId", userId == null ? null : 
Long.parseLong(userId));
         return query.executeUpdate();
     }
+
+    private List<Widget> expandProperties(List<JpaWidget> widgets) {
+        for(JpaWidget widget : widgets) {
+            expandProperties(widget);
+        }
+        return CollectionUtils.<Widget>toBaseTypedList(widgets);
+    }
+
+    private JpaWidget expandProperties(JpaWidget widget) {
+        if(widget != null) {
+            widget.deserializeData();
+        }
+        return widget;
+    }
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/model/conversion/JpaWidgetConverterTest.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/model/conversion/JpaWidgetConverterTest.java
 
b/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/model/conversion/JpaWidgetConverterTest.java
index e388cb1..f629021 100644
--- 
a/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/model/conversion/JpaWidgetConverterTest.java
+++ 
b/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/model/conversion/JpaWidgetConverterTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.rave.portal.model.conversion;
 
+import com.google.common.collect.Maps;
 import org.apache.rave.model.*;
 import org.apache.rave.portal.model.*;
 import org.apache.rave.portal.model.impl.WidgetImpl;
@@ -79,6 +80,7 @@ public class JpaWidgetConverterTest {
         template.setTags(new ArrayList<WidgetTag>());
         template.setCategories(new ArrayList<Category>());
         template.setFeatured(true);
+        template.setProperties(Maps.<String,Object>newHashMap());
 
         Widget jpaTemplate = converter.convert(template);
 
@@ -103,6 +105,7 @@ public class JpaWidgetConverterTest {
         assertThat(jpaTemplate.getTags(), is(equalTo(template.getTags())));
         assertThat(jpaTemplate.getCategories(), 
is(equalTo(template.getCategories())));
         assertThat(jpaTemplate.isFeatured(), 
is(equalTo(template.isFeatured())));
+        assertThat(jpaTemplate.getProperties(), 
is(equalTo(template.getProperties())));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/repository/impl/JpaWidgetRepositoryTest.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/repository/impl/JpaWidgetRepositoryTest.java
 
b/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/repository/impl/JpaWidgetRepositoryTest.java
index ad8c286..9835c0b 100644
--- 
a/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/repository/impl/JpaWidgetRepositoryTest.java
+++ 
b/rave-components/rave-jpa/src/test/java/org/apache/rave/portal/repository/impl/JpaWidgetRepositoryTest.java
@@ -19,8 +19,10 @@
 
 package org.apache.rave.portal.repository.impl;
 
+import com.google.common.collect.Maps;
 import org.apache.rave.model.*;
 import org.apache.rave.portal.model.*;
+import org.apache.rave.portal.model.impl.WidgetImpl;
 import org.apache.rave.portal.model.util.WidgetStatistics;
 import org.apache.rave.portal.repository.TagRepository;
 import org.apache.rave.portal.repository.WidgetRepository;
@@ -74,6 +76,7 @@ public class JpaWidgetRepositoryTest {
         JpaWidget widget = (JpaWidget)repository.get("1");
         assertThat(widget, is(notNullValue()));
         assertThat(widget.getEntityId(), is(equalTo(1L)));
+        validateProperties(widget);
     }
 
     @Test
@@ -85,10 +88,11 @@ public class JpaWidgetRepositoryTest {
     @Test
     public void getByUrl_valid() {
         final String widgetUrl =
-                
"http://hosting.gmodules.com/ig/gadgets/file/112581010116074801021/hamster.xml";;
+                "http://www.widget-dico.com/wikipedia/google/wikipedia.xml";;
         final Widget widget = repository.getByUrl(widgetUrl);
         assertNotNull(widget);
         assertEquals(widgetUrl, widget.getUrl());
+        validateProperties(widget);
     }
 
     @Test
@@ -110,6 +114,13 @@ public class JpaWidgetRepositoryTest {
     }
 
     @Test
+    public void getByFreeTextSearch_wiki() {
+        List<Widget> widgets = repository.getByFreeTextSearch("AA", 0, 1);
+        assertEquals(1, widgets.size());
+        validateProperties(widgets);
+    }
+
+    @Test
     public void countFreeTextSearch() {
         int count = repository.getCountFreeTextSearch("gAdGet");
         assertTrue(count >= 2);
@@ -120,14 +131,17 @@ public class JpaWidgetRepositoryTest {
         List<Widget> widgets = repository.getAll();
         assertThat(widgets, is(notNullValue()));
         assertThat(widgets.size() > 4, is(true));
+        validateProperties(widgets);
     }
 
     @Test
     public void getLimitedList() {
         final int pageSize = 3;
+        //Widget 1 should always appear in the list because the query is 
ordered
         List<Widget> widgets = repository.getLimitedList(0, pageSize);
         assertNotNull(widgets);
         assertTrue(widgets.size() <= pageSize);
+        validateProperties(widgets);
     }
 
     @Test
@@ -142,6 +156,7 @@ public class JpaWidgetRepositoryTest {
         List<Widget> published = 
repository.getByStatus(WidgetStatus.PUBLISHED, 0, pageSize);
         assertNotNull(published);
         assertTrue(published.size() > 0);
+        validateProperties(published);
 
         List<Widget> preview = repository.getByStatus(WidgetStatus.PREVIEW, 0, 
pageSize);
         assertNotNull(preview);
@@ -181,6 +196,16 @@ public class JpaWidgetRepositoryTest {
     }
 
     @Test
+    public void getByStatusAndTypeAndFreeText_wiki() {
+        final String searchTerm = "AA";
+        final String type = "OpenSocial";
+        List<Widget> widgets = 
repository.getByStatusAndTypeAndFreeTextSearch(WidgetStatus.PUBLISHED, type,
+                searchTerm, 0, 1);
+        assertEquals(1, widgets.size());
+        validateProperties(widgets);
+    }
+
+    @Test
     public void countByStatusAndTypeAndFreeText() {
         final String searchTerm = "gAdGet";
         final String type = "OpenSocial";
@@ -192,6 +217,7 @@ public class JpaWidgetRepositoryTest {
     public void getByOwner() {
         final User user = new JpaUser(2L);
         List<Widget> widgets = repository.getByOwner(user, 0, 10);
+        validateProperties(widgets);
         assertEquals(1, widgets.size());
     }
 
@@ -221,6 +247,36 @@ public class JpaWidgetRepositoryTest {
     }
 
     @Test
+    @Transactional(readOnly = false)
+    @Rollback
+    @SuppressWarnings("unchecked")
+    public void saveWidgetWithProperties() {
+        final String url = "http://example.com/doesnotexistyet";;
+        final String longDescription = "Foo";
+
+        Widget doesnotexist = repository.getByUrl(url);
+        assertNull(doesnotexist);
+
+        Map<String, Object> properties = Maps.newHashMap();
+        Map<String, String> sub = Maps.newHashMap();
+        sub.put("bar", "none");
+        properties.put("sub", sub);
+        properties.put("foo", "bar");
+
+        Widget widget = new WidgetImpl();
+        widget.setTitle("Widget with properties");
+        widget.setUrl(url);
+        widget.setDescription(longDescription);
+        widget.setProperties(properties);
+        widget = repository.save(widget);
+        assertNotNull(widget.getId());
+        assertEquals(longDescription, widget.getDescription());
+        assertEquals(widget.getProperties().get("foo"), "bar");
+        
assertEquals(((Map<String,String>)widget.getProperties().get("sub")).get("bar"),
 "none");
+        assertNotNull(((JpaWidget)widget).getSerializedData());
+    }
+
+    @Test
     public void getAllWidgetStatistics() {
         Map<String, WidgetStatistics> widgetStatistics = 
repository.getAllWidgetStatistics("1");
 
@@ -495,4 +551,19 @@ public class JpaWidgetRepositoryTest {
         repository.delete(widget);
         assertThat(repository.get(WIDGET_ID), is(nullValue()));
     }
+
+    private void validateProperties(List<Widget> widgets) {
+        for(Widget w: widgets) {
+            if(w.getId().equals("1")) {
+                validateProperties(w);
+                return;
+            }
+        }
+        throw new RuntimeException("Widget not found in test data");
+    }
+
+    private void validateProperties(Widget w) {
+        assertThat(w.getProperties(), is(not(nullValue())));
+        assertThat(w.getProperties().get("sub"), is(not(nullValue())));
+    }
 }

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-jpa/src/test/resources/test_data.sql
----------------------------------------------------------------------
diff --git a/rave-components/rave-jpa/src/test/resources/test_data.sql 
b/rave-components/rave-jpa/src/test/resources/test_data.sql
index 735d42b..1204b72 100644
--- a/rave-components/rave-jpa/src/test/resources/test_data.sql
+++ b/rave-components/rave-jpa/src/test/resources/test_data.sql
@@ -197,8 +197,8 @@ UPDATE RAVE_PORTAL_SEQUENCES SET seq_count = (seq_count + 
1) WHERE seq_name = @u
 --- gadget data ---
 -- wikipedia widget
 set @wikipedia_widget_id = (SELECT seq_count FROM RAVE_PORTAL_SEQUENCES WHERE 
seq_name = @widget_seq);
-insert into widget (entity_id, title, url, type, description, author, 
widget_status, owner_id)
-values(@wikipedia_widget_id, 
'Wikipedia','http://www.widget-dico.com/wikipedia/google/wikipedia.xml', 
'OpenSocial', 'A Wikipedia Search and Go widget. Language choice.', 'WidgetMe', 
'PUBLISHED', @user_id_2);
+insert into widget (entity_id, title, url, type, description, author, 
widget_status, serialized_data ,owner_id)
+values(@wikipedia_widget_id, 
'AA_Wikipedia','http://www.widget-dico.com/wikipedia/google/wikipedia.xml', 
'OpenSocial', 'A Wikipedia Search and Go widget. Language choice.', 'WidgetMe', 
'PUBLISHED', '{"sub":{"bar":"none"}, "foo":"bar"}', @user_id_2);
 UPDATE RAVE_PORTAL_SEQUENCES SET seq_count = (seq_count + 1) WHERE seq_name = 
@widget_seq;
 
 -- translate widget

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-mongodb/src/main/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverter.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-mongodb/src/main/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverter.java
 
b/rave-components/rave-mongodb/src/main/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverter.java
index 2dda35a..a15ab6e 100644
--- 
a/rave-components/rave-mongodb/src/main/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverter.java
+++ 
b/rave-components/rave-mongodb/src/main/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverter.java
@@ -138,6 +138,7 @@ public class MongoDbWidgetConverter implements 
HydratingModelConverter<Widget, M
         
converted.setDisableRenderingMessage(source.getDisableRenderingMessage());
         converted.setFeatured(source.isFeatured());
         converted.setOwnerId(source.getOwnerId());
+        converted.setProperties(source.getProperties());
     }
 
     public void setCategoryRepository(CategoryRepository categoryRepository) {

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-components/rave-mongodb/src/test/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverterTest.java
----------------------------------------------------------------------
diff --git 
a/rave-components/rave-mongodb/src/test/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverterTest.java
 
b/rave-components/rave-mongodb/src/test/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverterTest.java
index 54307cc..9261948 100644
--- 
a/rave-components/rave-mongodb/src/test/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverterTest.java
+++ 
b/rave-components/rave-mongodb/src/test/java/org/apache/rave/portal/model/conversion/impl/MongoDbWidgetConverterTest.java
@@ -20,6 +20,7 @@
 package org.apache.rave.portal.model.conversion.impl;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.apache.rave.model.*;
 import org.apache.rave.portal.model.*;
 import org.apache.rave.portal.model.impl.*;
@@ -142,6 +143,9 @@ public class MongoDbWidgetConverterTest {
         WidgetRating wr = new WidgetRatingImpl();
         source.getRatings().add(wr);
 
+        source.setProperties(Maps.<String, Object>newHashMap());
+        source.getProperties().put("sub", "foo");
+
         converted = converter.convert(source);
 
         assertThat(converted.getUrl(), is(equalTo("http://mitre.org";)));
@@ -181,6 +185,8 @@ public class MongoDbWidgetConverterTest {
         //Test convertRatings method
         assertNotNull(converted.getRatings());
         assertNotNull(converted.getRatings().get(0).getId());
+
+        assertThat((String)converted.getProperties().get("sub"), 
is(equalTo("foo")));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetWrapperRenderer.java
----------------------------------------------------------------------
diff --git 
a/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetWrapperRenderer.java
 
b/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetWrapperRenderer.java
index 99cdf35..04aa618 100644
--- 
a/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetWrapperRenderer.java
+++ 
b/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetWrapperRenderer.java
@@ -30,6 +30,7 @@ import 
org.apache.rave.portal.web.renderer.model.RenderContext;
 import org.apache.rave.provider.opensocial.Constants;
 import org.apache.rave.provider.opensocial.service.OpenSocialService;
 import org.apache.rave.provider.opensocial.service.SecurityTokenService;
+import org.apache.rave.util.JsonUtils;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.slf4j.Logger;
@@ -74,7 +75,8 @@ public class OpenSocialWidgetWrapperRenderer implements 
RegionWidgetWrapperRende
             " widgetId: '%9$s'," +
             " locked: %10$s," +
             " hideChrome: %11$s," +
-            " subPage: {id: %12$s, name: '%13$s', isDefault: %14$s}" +
+            " subPage: {id: %12$s, name: '%13$s', isDefault: %14$s}," +
+            " properties: %15$s" +
             "})});</script>";
     private static final String MARKUP = "<!-- RegionWidget '%1$s' placeholder 
-->";
 
@@ -154,7 +156,8 @@ public class OpenSocialWidgetWrapperRenderer implements 
RegionWidgetWrapperRende
                 item.isHideChrome(),
                 pageId,
                 pageName,
-                isDefault
+                isDefault,
+                JsonUtils.stringify(widget.getProperties())
                 );
     }
 

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
----------------------------------------------------------------------
diff --git 
a/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
 
b/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
index d165344..b81e108 100644
--- 
a/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
+++ 
b/rave-providers/rave-opensocial-provider/rave-opensocial-client/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.rave.provider.opensocial.web.renderer;
 
+import com.google.common.collect.Maps;
 import org.apache.rave.exception.NotSupportedException;
 import org.apache.rave.model.*;
 import org.apache.rave.portal.model.impl.*;
@@ -37,6 +38,7 @@ import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Map;
 
 import static org.easymock.EasyMock.*;
 import static org.hamcrest.CoreMatchers.equalTo;
@@ -96,6 +98,9 @@ public class OpenSocialWidgetRendererTest {
         w.setId(WIDGET_ID);
         w.setType(Constants.WIDGET_TYPE);
         w.setUrl(VALID_GADGET_URL);
+        Map<String, Object> props = Maps.newHashMap();
+        w.setProperties(props);
+        props.put("foo","bar");
 
         Region region = new RegionImpl(REGION_ID);
         region.setPage(subPage);
@@ -121,7 +126,8 @@ public class OpenSocialWidgetRendererTest {
                         " widgetId: '" + WIDGET_ID + "'," +
                         " locked: " + VALID_LOCKED + "," +
                         " hideChrome: " + VALID_HIDE_CHROME + "," +
-                        " subPage: {id: '" + VALID_SUBPAGE_ID + "', name: '" + 
VALID_SUBPAGE_NAME + "', isDefault: " + VALID_IS_DEFAULT_SUBPAGE + "}" +
+                        " subPage: {id: '" + VALID_SUBPAGE_ID + "', name: '" + 
VALID_SUBPAGE_NAME + "', isDefault: " + VALID_IS_DEFAULT_SUBPAGE + "}," +
+                        " properties: {\"foo\":\"bar\"}" +
                         "})" +
                         "});</script>";
 
@@ -171,7 +177,8 @@ public class OpenSocialWidgetRendererTest {
                         " widgetId: 'null'," +
                         " locked: false," +
                         " hideChrome: false," +
-                        " subPage: {id: null, name: '', isDefault: false}" +
+                        " subPage: {id: null, name: '', isDefault: false}," +
+                        " properties: null" +
                         "})" +
                         "});</script>";
 

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cRegionWidgetRenderer.java
----------------------------------------------------------------------
diff --git 
a/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cRegionWidgetRenderer.java
 
b/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cRegionWidgetRenderer.java
new file mode 100644
index 0000000..cbdbdc8
--- /dev/null
+++ 
b/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cRegionWidgetRenderer.java
@@ -0,0 +1,69 @@
+/*
+ * 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.rave.provider.w3c.web.renderer;
+
+
+import org.apache.rave.model.User;
+import org.apache.rave.portal.service.UserService;
+import org.apache.rave.portal.service.WidgetProviderService;
+import org.apache.rave.portal.service.WidgetService;
+import org.apache.rave.portal.web.renderer.RegionWidgetRenderer;
+import org.apache.rave.portal.web.renderer.model.RenderContext;
+import org.apache.rave.provider.w3c.service.impl.W3CWidget;
+import org.apache.rave.rest.model.RegionWidget;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import static org.apache.rave.provider.w3c.Constants.WIDGET_TYPE;
+
+@Component
+public class W3cRegionWidgetRenderer implements RegionWidgetRenderer {
+
+    private final WidgetProviderService widgetService;
+    private final UserService userService;
+    private final WidgetService coreWidgetService;
+
+    @Autowired
+    public W3cRegionWidgetRenderer(@Qualifier("wookieWidgetService") 
WidgetProviderService widgetService,
+                                    UserService userService, WidgetService 
coreWidgetService) {
+        this.widgetService = widgetService;
+        this.userService = userService;
+        this.coreWidgetService = coreWidgetService;
+    }
+
+    @Override
+    public String getSupportedContext() {
+        return WIDGET_TYPE;
+    }
+
+    @Override
+    public String render(RegionWidget item, RenderContext context) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public RegionWidget prepareForRender(RegionWidget item) {
+        User user = userService.getAuthenticatedUser();
+        String sharedDataKey = String.valueOf(item.getId());
+        W3CWidget contextualizedWidget = (W3CWidget) 
widgetService.getWidget(user, sharedDataKey, 
coreWidgetService.getWidget(item.getWidgetId()));
+        item.setWidgetUrl(contextualizedWidget.getUrl());
+        return item;
+    }
+}

http://git-wip-us.apache.org/repos/asf/rave/blob/3909e6e0/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetWrapperRenderer.java
----------------------------------------------------------------------
diff --git 
a/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetWrapperRenderer.java
 
b/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetWrapperRenderer.java
index ccb18b8..d1e9462 100644
--- 
a/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetWrapperRenderer.java
+++ 
b/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetWrapperRenderer.java
@@ -30,6 +30,7 @@ import org.apache.rave.portal.web.renderer.ScriptManager;
 import org.apache.rave.portal.web.renderer.model.RegionWidgetWrapper;
 import org.apache.rave.portal.web.renderer.model.RenderContext;
 import org.apache.rave.provider.w3c.service.impl.W3CWidget;
+import org.apache.rave.util.JsonUtils;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.slf4j.Logger;
@@ -74,7 +75,8 @@ public class W3cWidgetWrapperRenderer implements 
RegionWidgetWrapperRenderer {
         " widgetId: %8$s, " +
         " locked: %9$s, " +
         " hideChrome: %10$s, " +
-        " subPage: {id: %11$s, name: '%12$s', isDefault: %13$s}" +
+        " subPage: {id: %11$s, name: '%12$s', isDefault: %13$s}," +
+        " properties: %14$s" +
         "})});</script>";
     private static final String MARKUP = "<!-- RegionWidget %1$s placeholder 
-->";
 
@@ -188,7 +190,8 @@ public class W3cWidgetWrapperRenderer implements 
RegionWidgetWrapperRenderer {
                 item.isHideChrome(),
                 pageId,
                 pageName,
-                isDefault);
+                isDefault,
+                JsonUtils.stringify(widget.getProperties()));
     }
 
     private boolean isDefaultSubPage(Page subPage) {

Reply via email to