You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ps...@apache.org on 2012/05/08 20:50:12 UTC

svn commit: r1335687 [1/3] - in /rave/trunk: rave-components/rave-core/src/main/java/org/apache/rave/portal/model/ rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/ rave-components/rave-core/src/main/java/org/apache/rave/portal...

Author: psharples
Date: Tue May  8 18:50:10 2012
New Revision: 1335687

URL: http://svn.apache.org/viewvc?rev=1335687&view=rev
Log:
Updates and changes to implement page sharing between rave users. See RAVE-103. (Support shared spaces.)

Added:
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java   (with props)
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java   (with props)
    rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/UserApi.java   (with props)
Modified:
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Page.java
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/PageRepository.java
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaPageRepository.java
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
    rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java
    rave/trunk/rave-components/rave-core/src/main/resources/META-INF/persistence.xml
    rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/PageTest.java
    rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/impl/JpaPageRepositoryTest.java
    rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultPageServiceTest.java
    rave/trunk/rave-components/rave-core/src/test/resources/test_data.sql
    rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java
    rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/PageController.java
    rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java
    rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/PageControllerTest.java
    rave/trunk/rave-portal-resources/src/main/resources/messages.properties
    rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties
    rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/db/initial_data.sql
    rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/page.jsp
    rave/trunk/rave-portal-resources/src/main/webapp/css/default.css
    rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js
    rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js
    rave/trunk/rave-portal/src/test/resources/test-data.sql

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Page.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Page.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Page.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/Page.java Tue May  8 18:50:10 2012
@@ -46,15 +46,13 @@ import java.util.List;
 @XmlAccessorType(XmlAccessType.NONE)
 @Table(name="page", uniqueConstraints={@UniqueConstraint(columnNames={"owner_id","name","page_type"})})
 @NamedQueries({
-        @NamedQuery(name = Page.GET_BY_USER_ID_AND_PAGE_TYPE, query="SELECT p FROM Page p WHERE p.owner.entityId = :userId and p.pageType = :pageType ORDER BY p.renderSequence"),
         @NamedQuery(name = Page.DELETE_BY_USER_ID_AND_PAGE_TYPE, query="DELETE FROM Page p WHERE p.owner.entityId = :userId and p.pageType = :pageType"),
         @NamedQuery(name = Page.USER_HAS_PERSON_PAGE, query="SELECT count(p) FROM Page p WHERE p.owner.entityId = :userId and p.pageType = :pageType")
 })
 @Access(AccessType.FIELD)
 public class Page implements BasicEntity, Serializable {
     private static final long serialVersionUID = 1L;
-    
-    public static final String GET_BY_USER_ID_AND_PAGE_TYPE = "Page.getByUserIdAndPageType";
+
     public static final String DELETE_BY_USER_ID_AND_PAGE_TYPE = "Page.deleteByUserIdAndPageType";
     public static final String USER_HAS_PERSON_PAGE = "Page.hasPersonPage";
 
@@ -78,12 +76,8 @@ public class Page implements BasicEntity
     private Page parentPage;
 
     @OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL, mappedBy="parentPage")
-    @OrderBy("renderSequence")
     private List<Page> subPages;
 
-    @Basic(optional=false) @Column(name="render_sequence")
-    private Long renderSequence;
-
     @ManyToOne
     @JoinColumn(name="page_layout_id")
     private PageLayout pageLayout;
@@ -98,6 +92,21 @@ public class Page implements BasicEntity
     @Column(name = "page_type")
     @Enumerated(EnumType.STRING)
     private PageType pageType;
+    
+    @OneToMany(targetEntity=PageUser.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="page", orphanRemoval=true)
+    private List<PageUser> members;
+
+    @JsonManagedReference
+    public List<PageUser> getMembers() {
+        return members;
+    }
+
+    /**
+     * @param members the members to set
+     */
+    public void setMembers(List<PageUser> members) {
+       this.members = members;
+    }
 
     public Page() {
     }
@@ -153,20 +162,6 @@ public class Page implements BasicEntity
     }
 
     /**
-     * Gets the order of the page instance relative to all pages for the owner (useful when presenting pages in an
-     * ordered layout like tabs or an accordion container)
-     *
-     * @return Valid, unique render sequence
-     */
-    public Long getRenderSequence() {
-        return renderSequence;
-    }
-
-    public void setRenderSequence(Long renderSequence) {
-        this.renderSequence = renderSequence;
-    }
-
-    /**
      * Gets the {@link PageLayout}
      *
      * @return Valid {@link PageLayout}
@@ -241,6 +236,6 @@ public class Page implements BasicEntity
 
     @Override
     public String toString() {
-        return "Page{" + "entityId=" + entityId + ", name=" + name + ", owner=" + owner + ", renderSequence=" + renderSequence + ", pageLayout=" + pageLayout + ", pageType=" + pageType + "}";
+        return "Page{" + "entityId=" + entityId + ", name=" + name + ", owner=" + owner + ", pageLayout=" + pageLayout + ", pageType=" + pageType + "}";
     }
 }

Added: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java?rev=1335687&view=auto
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java (added)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java Tue May  8 18:50:10 2012
@@ -0,0 +1,58 @@
+/*
+ * 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.portal.model;
+
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * The invitation status of a page - either its the owner, or a shared page
+ * which is pending (not yet accepted) refused or accepted by the shared to user  
+ */
+public enum PageInvitationStatus {
+    OWNER("owner"),
+    PENDING("pending"),
+    REFUSED("refused"),
+    ACCEPTED("accepted");
+
+    private String pageStatus;
+    private static final Map<String, PageInvitationStatus> lookup = new HashMap<String, PageInvitationStatus>();
+
+    static {
+        for (PageInvitationStatus pt : PageInvitationStatus.values()) {
+            lookup.put(pt.toString(), pt);
+        }
+    }
+
+    private PageInvitationStatus(String pageStatus) {
+        this.pageStatus = pageStatus;
+    }
+
+    public String getPageStatus() {
+        return pageStatus;
+    }
+
+    @Override
+    public String toString() {
+        return pageStatus;
+    }
+
+    public static PageInvitationStatus get(String pageStatus) {
+        return lookup.get(pageStatus);
+    }
+}

Propchange: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageInvitationStatus.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java?rev=1335687&view=auto
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java (added)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java Tue May  8 18:50:10 2012
@@ -0,0 +1,172 @@
+/*
+ * 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.portal.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Basic;
+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.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import org.apache.rave.persistence.BasicEntity;
+import org.codehaus.jackson.annotate.JsonBackReference;
+@Entity
+@Table(name = "page_user", uniqueConstraints={@UniqueConstraint(columnNames={"page_id","user_id"})})
+
+@NamedQueries({
+        @NamedQuery(name = PageUser.GET_BY_USER_ID_AND_PAGE_TYPE, query="SELECT p.page FROM PageUser p, Page q WHERE p.page.entityId = q.entityId and p.user.entityId = :userId and q.pageType = :pageType ORDER BY p.renderSequence"),
+        @NamedQuery(name = PageUser.GET_PAGES_FOR_USER, query="SELECT p FROM PageUser p, Page q WHERE p.page.entityId = q.entityId and p.user.entityId = :userId and q.pageType = :pageType ORDER BY p.renderSequence"),
+        @NamedQuery(name = PageUser.GET_SINGLE_RECORD, query="SELECT p FROM PageUser p WHERE p.user.entityId = :userId and p.page.entityId = :pageId")
+})
+public class PageUser implements BasicEntity, Serializable {
+    private static final long serialVersionUID = 1L;
+    
+    public static final String GET_BY_USER_ID_AND_PAGE_TYPE ="PageUser.getByUserIdAndPageType";
+    public static final String GET_PAGES_FOR_USER = "PageUser.getPagesForUser";
+    public static final String GET_SINGLE_RECORD = "PageUser.getSingleRecord";
+    
+    @Id @Column(name="entity_id")
+    @GeneratedValue(strategy = GenerationType.TABLE, generator = "pageUserIdGenerator")
+    @TableGenerator(name = "pageUserIdGenerator", table = "RAVE_PORTAL_SEQUENCES", pkColumnName = "SEQ_NAME",
+            valueColumnName = "SEQ_COUNT", pkColumnValue = "page_user", allocationSize = 1, initialValue = 1)
+            
+    private Long entityId;
+    
+    @ManyToOne
+    @JoinColumn(name = "user_id")
+    private User user;
+    
+    @ManyToOne(fetch=FetchType.EAGER)
+    @JoinColumn(name = "page_id", nullable=false)
+    private Page page;
+    
+    private boolean editor;
+    
+    @Basic(optional=false) @Column(name="render_sequence")
+    private Long renderSequence;
+    
+    @Basic
+    @Column(name = "page_status")
+    @Enumerated(EnumType.STRING)
+    private PageInvitationStatus pageStatus;
+    
+    public Long getEntityId() {
+        return entityId;
+    }
+
+    public void setEntityId(Long entityId) {
+        this.entityId = entityId;
+    }
+	
+    /**
+	 * @return the editor
+	 */
+	public boolean isEditor() {
+        return editor;
+	}
+
+    /**
+    * @param editor the editor to set
+    */
+    public void setEditor(boolean editor) {
+        this.editor = editor;
+    }
+
+    /**
+    * @return the user
+    */
+    public User getUser() {
+        return user;
+    }
+
+    /**
+    * @param user the user to set
+    */
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    /**
+    * @return the page
+    */
+    @JsonBackReference
+    public Page getPage() {
+        return page;
+    }
+
+    /**
+    * @param page the page to set
+    */
+    public void setPage(Page page) {
+        this.page = page;
+    }
+
+    /**
+     * Gets the order of the page instance relative to all pages for the owner (useful when presenting pages in an
+     * ordered layout like tabs or an accordion container)
+     *
+     * @return Valid, unique render sequence
+     */
+    public Long getRenderSequence() {
+        return renderSequence;
+    }
+
+    public void setRenderSequence(Long renderSequence) {
+        this.renderSequence = renderSequence;
+    }
+
+    /**
+     * Get the page status - used in shared states where a page can be pending, refused or accepted
+     * Only applies to shared pages
+     * @return an enum type
+     */
+    public PageInvitationStatus getPageStatus() {
+        return pageStatus;
+    }
+
+    public void setPageStatus(PageInvitationStatus pageStatus) {
+        this.pageStatus = pageStatus;
+    }
+    
+    public PageUser(){}
+    
+    public PageUser(User user, Page page){
+        this.user = user;
+        this.page = page;
+    }
+
+    public PageUser(User user, Page page, long sequence){
+        this.user = user;
+        this.page = page;
+        this.renderSequence = sequence;
+    }
+}

Propchange: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/model/PageUser.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/PageRepository.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/PageRepository.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/PageRepository.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/PageRepository.java Tue May  8 18:50:10 2012
@@ -22,6 +22,7 @@ import org.apache.rave.persistence.Repos
 import org.apache.rave.portal.model.Page;
 import org.apache.rave.portal.model.PageTemplate;
 import org.apache.rave.portal.model.PageType;
+import org.apache.rave.portal.model.PageUser;
 import org.apache.rave.portal.model.User;
 
 import java.util.List;
@@ -62,4 +63,22 @@ public interface PageRepository extends 
      * @return boolean
      */
     boolean hasPersonPage(long userId);
+
+    /**
+     * Returns a list of pageUser records of a certain pageType.  
+     * Used to get a list of a users pages(user) with render sequencing. 
+     * @param userId
+     * @param pageType
+     * @return a list of pageUser
+     */
+    public List<PageUser> getPagesForUser(Long userId, PageType pageType);
+    
+
+    /**
+     * Returns a single pageUser tuple based on userId and pageId
+     * @param userId
+     * @param pageId
+     * @return a single pageUser
+     */
+    public PageUser getSingleRecord(Long userId, Long pageId);
 }
\ No newline at end of file

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaPageRepository.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaPageRepository.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaPageRepository.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/repository/impl/JpaPageRepository.java Tue May  8 18:50:10 2012
@@ -37,7 +37,7 @@ public class JpaPageRepository extends A
 
     @Override
     public List<Page> getAllPages(Long userId, PageType pageType) {
-        TypedQuery<Page> query = manager.createNamedQuery(Page.GET_BY_USER_ID_AND_PAGE_TYPE, Page.class);
+        TypedQuery<Page> query = manager.createNamedQuery(PageUser.GET_BY_USER_ID_AND_PAGE_TYPE, Page.class);
         query.setParameter("userId", userId);
         query.setParameter("pageType", pageType);
         return query.getResultList();
@@ -50,7 +50,7 @@ public class JpaPageRepository extends A
         query.setParameter("pageType", pageType);
         return query.executeUpdate();
     }
-    
+
     @Override
     public boolean hasPersonPage(long userId){
         TypedQuery<Long> query = manager.createNamedQuery(Page.USER_HAS_PERSON_PAGE, Long.class);
@@ -60,9 +60,25 @@ public class JpaPageRepository extends A
     }
 
     @Override
+    public List<PageUser> getPagesForUser(Long userId, PageType pageType) {
+        TypedQuery<PageUser> query = manager.createNamedQuery(PageUser.GET_PAGES_FOR_USER, PageUser.class);
+        query.setParameter("userId", userId);
+        query.setParameter("pageType", pageType);
+        return query.getResultList();
+    }
+
+    @Override
+    public PageUser getSingleRecord(Long userId, Long pageId){
+        TypedQuery<PageUser> query = manager.createNamedQuery(PageUser.GET_SINGLE_RECORD, PageUser.class);
+        query.setParameter("userId", userId);
+        query.setParameter("pageId", pageId);
+        return query.getSingleResult();
+    }
+
+    @Override
     public Page createPageForUser(User user, PageTemplate pt) {
         Page personPageFromTemplate = convert(pt, user);
-        return save(personPageFromTemplate);
+        return personPageFromTemplate;
     }
 
     /**
@@ -77,10 +93,16 @@ public class JpaPageRepository extends A
         p.setName(pt.getName());
         p.setPageType(pt.getPageType());
         p.setOwner(user);
-        p.setRenderSequence(pt.getRenderSequence());
+        PageUser pageUser = new PageUser(p.getOwner(), p, pt.getRenderSequence());
+        pageUser.setPageStatus(PageInvitationStatus.OWNER);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(pageUser);
+        p.setMembers(members);
+
         p.setPageLayout(pt.getPageLayout());
         p.setRegions(convertRegions(pt.getPageTemplateRegions(), p));
         p.setSubPages(convertPages(pt.getSubPageTemplates(), p));
+        p = save(p);
         return p;
     }
 
@@ -137,18 +159,26 @@ public class JpaPageRepository extends A
     private List<Page> convertPages(List<PageTemplate> pageTemplates, Page page){
         List<Page> pages = new ArrayList<Page>();
         for(PageTemplate pt : pageTemplates){
-            Page p = new Page();
-            p.setName(pt.getName());
-            p.setPageType(pt.getPageType());
-            p.setOwner(page.getOwner());
-            p.setPageLayout(pt.getPageLayout());
-            p.setParentPage(page);
-            p.setRenderSequence(pt.getRenderSequence());
-            p.setRegions(convertRegions(pt.getPageTemplateRegions(), p));
+            Page lPage = new Page();
+            lPage.setName(pt.getName());
+            lPage.setPageType(pt.getPageType());
+            lPage.setOwner(page.getOwner());
+            lPage.setPageLayout(pt.getPageLayout());
+            lPage.setParentPage(page);
+            lPage.setRegions(convertRegions(pt.getPageTemplateRegions(), lPage));
+            
+            // create new pageUser tuple
+            PageUser pageUser = new PageUser(lPage.getOwner(), lPage, pt.getRenderSequence());
+            pageUser.setPageStatus(PageInvitationStatus.OWNER);
+            List<PageUser> members = new ArrayList<PageUser>();
+            members.add(pageUser);
+            lPage.setMembers(members);
             // recursive call
-            p.setSubPages((pt.getSubPageTemplates() == null || pt.getSubPageTemplates().isEmpty()) ? null : convertPages(pt.getSubPageTemplates(), p));
-            pages.add(p);
+            lPage.setSubPages((pt.getSubPageTemplates() == null || pt.getSubPageTemplates().isEmpty()) ? null : convertPages(pt.getSubPageTemplates(), lPage));
+            lPage = save(lPage);
+            pages.add(lPage);
         }
         return pages;
     }
+
 }
\ No newline at end of file

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/security/impl/DefaultPagePermissionEvaluator.java Tue May  8 18:50:10 2012
@@ -20,6 +20,7 @@ package org.apache.rave.portal.security.
 
 import org.apache.rave.portal.model.Page;
 import org.apache.rave.portal.model.PageType;
+import org.apache.rave.portal.model.PageUser;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.repository.PageRepository;
 import org.slf4j.Logger;
@@ -116,7 +117,8 @@ public class DefaultPagePermissionEvalua
             case DELETE:            
             case UPDATE:
                 // anyone can create, delete, or update a page that they own                  
-                hasPermission = isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject);     
+                hasPermission = isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject)
+                || isPageMember(authentication, page, trustedPageContainer, trustedDomainObject);     
                 break;
             case READ:
                 // anyone can read a USER page they own or anyone's PERSON_PROFILE page
@@ -184,7 +186,8 @@ public class DefaultPagePermissionEvalua
     // anyone can read a User page they own or anyone's Person Profile page and sub-pages
     private boolean isReadablePage(Authentication authentication, Page page, List<Page> trustedPageContainer, boolean trustedDomainObject) {
         return isPersonProfilePageOrSubPage(page) ||
-               isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject);
+               isPageOwner(authentication, page, trustedPageContainer, trustedDomainObject) ||
+               isPageMember(authentication, page, trustedPageContainer, trustedDomainObject);
     }
     
     private boolean isPersonProfilePageOrSubPage(Page page) {
@@ -192,4 +195,35 @@ public class DefaultPagePermissionEvalua
         PageType parentPageType = (page.getParentPage() == null) ? null : page.getParentPage().getPageType();
         return PageType.PERSON_PROFILE.equals(pageType) || PageType.PERSON_PROFILE.equals(parentPageType);
     }  
+    
+    // checks to see if the Authentication object principal is a member of the supplied page object 
+    // if trustedDomainObject is false, pull the entity from the database first to ensure
+    // the model object is trusted and hasn't been modified
+    private boolean isPageMember(Authentication authentication, Page page, List<Page> trustedPageContainer, boolean trustedDomainObject) {
+        Page trustedPage = null;
+        if (trustedDomainObject) {
+            trustedPage = page;
+        } else {
+            trustedPage = getTrustedPage(page.getEntityId(), trustedPageContainer);
+        }
+        //
+        // If the page has no members, there can be no member access
+        //
+        if (trustedPage.getMembers() == null){
+            return false;
+        }
+        //
+        // Check that the viewer is a member
+        //
+        String viewer = ((User)authentication.getPrincipal()).getUsername();
+        for (PageUser pageUser:trustedPage.getMembers()){
+            if (pageUser.getUser().getUsername().equals(viewer)){
+                log.info("User "+viewer+" is a member of page "+trustedPage.getEntityId());
+                return true;
+            }
+        }
+        log.info("User "+viewer+" is NOT a member of page "+trustedPage.getEntityId());
+        return false;
+    }
+
 }
\ No newline at end of file

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java Tue May  8 18:50:10 2012
@@ -20,7 +20,6 @@ package org.apache.rave.portal.service;
 
 import org.apache.rave.portal.model.*;
 import org.springframework.security.access.prepost.PostAuthorize;
-import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.access.prepost.PreAuthorize;
 
 import java.util.List;
@@ -35,7 +34,7 @@ public interface PageService {
      * @param pageId to lookup
      * @return the Page object 
      */
-    @PostAuthorize("hasPermission(returnObject, 'read')")    
+    @PostAuthorize("hasPermission(returnObject, 'read')")
     Page getPage(long pageId);
     
     /**
@@ -203,4 +202,31 @@ public interface PageService {
      */
     @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')") 
     Page movePageToDefault(long pageId);
+
+    /**
+     * Add another user to share this page with
+     * @param pageId - the id of the page in question
+     * @param userId - the userid to add
+     * @return true or false whether the user was added
+     */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")
+    Boolean addMemberToPage(long pageId, long userId);
+    
+    /**
+     * Remove an existing user from the page share
+     * @param pageId - the id of the page in question
+     * @param userId - the userid to add
+     * @return -  whether the user was successfully removed or not
+     */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")
+    Boolean removeMemberFromPage(long pageId, long userId);
+
+    /**
+     * Allows a user to accept or decline a page share
+     * @param pageId - the id of the page in question
+     * @param shareStatus - a string value defined in PageStatus
+     * @return
+     */
+    @PreAuthorize("hasPermission(#pageId, 'org.apache.rave.portal.model.Page', 'update')")
+    Boolean updateSharedPageStatus(long pageId, String shareStatus);
 }
\ No newline at end of file

Modified: rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java (original)
+++ rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java Tue May  8 18:50:10 2012
@@ -19,9 +19,28 @@
 
 package org.apache.rave.portal.service.impl;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.NoResultException;
+import javax.persistence.NonUniqueResultException;
+
 import org.apache.rave.persistence.Repository;
-import org.apache.rave.portal.model.*;
-import org.apache.rave.portal.repository.*;
+import org.apache.rave.portal.model.Page;
+import org.apache.rave.portal.model.PageInvitationStatus;
+import org.apache.rave.portal.model.PageLayout;
+import org.apache.rave.portal.model.PageType;
+import org.apache.rave.portal.model.PageUser;
+import org.apache.rave.portal.model.Region;
+import org.apache.rave.portal.model.RegionWidget;
+import org.apache.rave.portal.model.User;
+import org.apache.rave.portal.model.Widget;
+import org.apache.rave.portal.repository.PageLayoutRepository;
+import org.apache.rave.portal.repository.PageRepository;
+import org.apache.rave.portal.repository.PageTemplateRepository;
+import org.apache.rave.portal.repository.RegionRepository;
+import org.apache.rave.portal.repository.RegionWidgetRepository;
+import org.apache.rave.portal.repository.WidgetRepository;
 import org.apache.rave.portal.service.PageService;
 import org.apache.rave.portal.service.UserService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,11 +48,6 @@ import org.springframework.beans.factory
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.persistence.NoResultException;
-import javax.persistence.NonUniqueResultException;
-import java.util.ArrayList;
-import java.util.List;
-
 @Service
 public class DefaultPageService implements PageService {
     private final PageRepository pageRepository;
@@ -139,10 +153,15 @@ public class DefaultPageService implemen
         page.setName(pageName);
         page.setOwner(user);
         page.setPageLayout(pageLayout);
-        page.setRenderSequence(renderSequence);
         page.setRegions(regions);
         // set this as a "sub-page" page type
         page.setPageType(PageType.SUB_PAGE);
+        
+        PageUser pageUser = new PageUser(page.getOwner(), page, renderSequence);
+        pageUser.setPageStatus(PageInvitationStatus.OWNER);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(pageUser);
+        page.setMembers(members);
 
         // Properly sets both sides of the circular parent-child reference
         page.setParentPage(parentPage);
@@ -151,7 +170,6 @@ public class DefaultPageService implemen
         }
         parentsSubPages.add(page);
         parentPage.setSubPages(parentsSubPages);
-
         pageRepository.save(page);
 
         return page;
@@ -172,8 +190,8 @@ public class DefaultPageService implemen
 
         //TODO RAVE-237:  We should be able to delete these lines.  If there are gaps in the sequence numbers, then it will still
         //TODO RAVE-237:  return values in the correct order.  We only need to update sequences when there is a change in order
-        List<Page> pages = pageRepository.getAllPages(user.getEntityId(), PageType.USER);
-        updatePageRenderSequences(pages);
+        List<PageUser> thisUsersPages = new ArrayList<PageUser>(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER));
+        updatePageRenderSequences(thisUsersPages);
     }
 
     @Override
@@ -201,7 +219,7 @@ public class DefaultPageService implemen
     
     @Override
     @Transactional
-    public RegionWidget moveRegionWidgetToPage(long regionWidgetId, long toPageId) {                
+    public RegionWidget moveRegionWidgetToPage(long regionWidgetId, long toPageId) {
         // Get the new page
         Page toPage = getFromRepository(toPageId, pageRepository);
         // Get the region widget
@@ -221,8 +239,8 @@ public class DefaultPageService implemen
         updateRenderSequences(moveToRegion.getRegionWidgets());
         // persist it
         regionRepository.save(moveToRegion);
-        return getFromRepository(regionWidgetId, regionWidgetRepository);        
-    }    
+        return getFromRepository(regionWidgetId, regionWidgetRepository);
+    }
 
     @Override
     @Transactional
@@ -251,8 +269,8 @@ public class DefaultPageService implemen
 
     @Override
     @Transactional
-    public Page movePageToDefault(long pageId) {    
-        return doMovePage(pageId, MOVE_PAGE_DEFAULT_POSITION_INDEX);    
+    public Page movePageToDefault(long pageId) {
+        return doMovePage(pageId, MOVE_PAGE_DEFAULT_POSITION_INDEX);
     }
 
     @Override
@@ -284,6 +302,60 @@ public class DefaultPageService implemen
 
         return page;
     }
+    
+    @Transactional
+    public Boolean addMemberToPage(long pageId, long userId){
+        Page page = getPage(pageId);
+        PageUser pageUser = new PageUser();
+        pageUser.setUser(userService.getUserById(userId));
+        pageUser.setPage(page);
+        pageUser.setPageStatus(PageInvitationStatus.PENDING);
+        List<PageUser> thisUsersPages = pageRepository.getPagesForUser(userService.getUserById(userId).getEntityId(), PageType.USER);
+        pageUser.setRenderSequence(new Long(thisUsersPages.size() + 1));
+        page.getMembers().add(pageUser);
+        if(pageRepository.save(page) != null){
+            return Boolean.TRUE;
+        }else{
+            return Boolean.FALSE;
+        }
+    }
+
+    @Transactional
+    public Boolean removeMemberFromPage(long pageId, long userId){
+        Page page = this.getPage(pageId);
+        PageUser pageUserToRemove = null;
+        for(PageUser pageUser : page.getMembers()){
+            if(pageUser.getUser().getEntityId().equals(userId)){
+                pageUserToRemove = pageUser;
+                break;
+            }
+        }
+        if(pageUserToRemove != null){
+            page.getMembers().remove(pageUserToRemove);
+            if(pageRepository.save(page) != null){
+                return Boolean.TRUE;
+            }else{
+                return Boolean.FALSE;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    @Transactional
+    public Boolean updateSharedPageStatus(long pageId, String shareStatus) {
+        Page page = this.getPage(pageId);
+        for(PageUser pageUser : page.getMembers()){
+            if(pageUser.getUser().equals(userService.getAuthenticatedUser())){
+                pageUser.setPageStatus(PageInvitationStatus.get(shareStatus));
+            }
+        }
+        if(pageRepository.save(page) != null){
+            return Boolean.TRUE;
+        }else{
+            return Boolean.FALSE;
+        }
+    }
 
     /**
      * Utility function to determine if a Page layout adjustment is needed
@@ -392,7 +464,6 @@ public class DefaultPageService implemen
 
     private Page addNewUserPage(User user, String pageName, String pageLayoutCode) {
         PageLayout pageLayout = pageLayoutRepository.getByPageLayoutCode(pageLayoutCode);
-
         // Create regions
         List<Region> regions = new ArrayList<Region>();
         int regionCount;
@@ -403,7 +474,6 @@ public class DefaultPageService implemen
             region.setLocked(false);
             regions.add(region);
         }
-
         // Get all User Pages
         Page page = null;
         List<Page> defaultUserPage = pageRepository.getAllPages(user.getEntityId(), PageType.USER);
@@ -426,7 +496,13 @@ public class DefaultPageService implemen
         page.setName(pageName);
         page.setOwner(user);
         page.setPageLayout(pageLayout);
-        page.setRenderSequence(renderSequence);
+        PageUser pageUser = new PageUser(page.getOwner(), page, renderSequence);
+        pageUser.setPageStatus(PageInvitationStatus.OWNER);
+
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(pageUser);
+        page.setMembers(members);
+
         page.setRegions(regions);
         // set this as a "user" page type
         page.setPageType(PageType.USER);
@@ -434,53 +510,47 @@ public class DefaultPageService implemen
         return page;
     }
 
-    private void updatePageRenderSequences(List<Page> pages) {       
+    private void updatePageRenderSequences(List<PageUser> pages) {
         if (pages != null && !pages.isEmpty()) {
             for (int i = 0; i < pages.size(); i++) {
-                Page p = pages.get(i);                
-                p.setRenderSequence((long)i+1);                               
+                PageUser p = pages.get(i);
+                p.setRenderSequence((long)i+1);
             }
 
-            for (Page page : pages) {
-                pageRepository.save(page);
+            for (PageUser page : pages) {
+                pageRepository.save(page.getPage());
             }
-        }       
+        }
     } 
-    
+
     private Page doMovePage(long pageId, long moveAfterPageId) {
         // get the logged in user
         User user = userService.getAuthenticatedUser();
-
         // get the page to move and the page to move after
-        Page movingPage = pageRepository.get(pageId);
-        Page afterPage = null;
+        PageUser movingPageUser = pageRepository.getSingleRecord(user.getEntityId(), pageId);
+        PageUser afterPageUser = null;
         int newIndex = 0;
-        
         // check to see if we should move the page to beginning
         if (moveAfterPageId != MOVE_PAGE_DEFAULT_POSITION_INDEX) {
-            afterPage = pageRepository.get(moveAfterPageId);
+            afterPageUser = pageRepository.getSingleRecord(user.getEntityId(), moveAfterPageId);
         }
 
         // get all of the user's pages
         // the pageRepository returns an un-modifiable list
         // so we need to create a modifyable arraylist
-        List<Page> pages = new ArrayList<Page>(pageRepository.getAllPages(user.getEntityId(), PageType.USER));
-
-        // first remove it from the list         
-        if (!pages.remove(movingPage)) {
+        List<PageUser> thisUsersPages = new ArrayList<PageUser>(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER));
+        // first remove it from the list   
+        if (!thisUsersPages.remove(movingPageUser)) {
             throw new RuntimeException("unable to find pageId " + pageId + " attempted to be moved for user " + user);
         }
 
-        // ...now re-insert in new location
-        if (afterPage != null) {
-            newIndex = pages.indexOf(afterPage) + 1;
+        if (afterPageUser != null) {
+            newIndex = thisUsersPages.indexOf(afterPageUser) + 1;
         }
-        pages.add(newIndex, movingPage);
-
+        thisUsersPages.add(newIndex, movingPageUser);
         // persist the new page order
-        updatePageRenderSequences(pages);
-        
-        return movingPage;
+        updatePageRenderSequences(thisUsersPages);
+        return movingPageUser.getPage();
     }
 
     private static <T> T getFromRepository(long id, Repository<T> repo) {

Modified: rave/trunk/rave-components/rave-core/src/main/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/main/resources/META-INF/persistence.xml?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/main/resources/META-INF/persistence.xml (original)
+++ rave/trunk/rave-components/rave-core/src/main/resources/META-INF/persistence.xml Tue May  8 18:50:10 2012
@@ -39,5 +39,6 @@
             <class>org.apache.rave.portal.model.PageTemplate</class>
             <class>org.apache.rave.portal.model.PageTemplateRegion</class>
             <class>org.apache.rave.portal.model.PageTemplateWidget</class>
+            <class>org.apache.rave.portal.model.PageUser</class>
         </persistence-unit>
 </persistence>

Modified: rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/PageTest.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/PageTest.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/PageTest.java (original)
+++ rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/model/PageTest.java Tue May  8 18:50:10 2012
@@ -41,6 +41,7 @@ public class PageTest {
 	private PageLayout pageLayout;
 	private long renderSequence;
 	private List<Region> regions;
+	private PageUser pageUser;
 	
 	@Before
 	public void setup(){
@@ -66,8 +67,12 @@ public class PageTest {
 		page.setParentPage(parentPage);
 		page.setSubPages(subPages);
 		page.setPageLayout(pageLayout);
-		page.setRenderSequence(renderSequence);
 		page.setRegions(regions);
+		
+		pageUser = new PageUser();
+		pageUser.setPage(page);
+		pageUser.setUser(testOwner);
+		pageUser.setRenderSequence(renderSequence);
 	}
 	
 	@After
@@ -83,7 +88,7 @@ public class PageTest {
 		assertTrue(page.getParentPage().equals(parentPage));
 		assertTrue(page.getSubPages().equals(subPages));
 		assertTrue(page.getPageLayout().equals(pageLayout));
-		assertTrue(page.getRenderSequence()==renderSequence);
+		assertTrue(pageUser.getRenderSequence()==renderSequence);
 	}
 
 	@Test

Modified: rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/impl/JpaPageRepositoryTest.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/impl/JpaPageRepositoryTest.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/impl/JpaPageRepositoryTest.java (original)
+++ rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/repository/impl/JpaPageRepositoryTest.java Tue May  8 18:50:10 2012
@@ -21,6 +21,7 @@ package org.apache.rave.portal.repositor
 import org.apache.rave.portal.model.Page;
 import org.apache.rave.portal.model.PageTemplate;
 import org.apache.rave.portal.model.PageType;
+import org.apache.rave.portal.model.PageUser;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.repository.PageRepository;
 import org.apache.rave.portal.repository.PageTemplateRepository;
@@ -62,7 +63,7 @@ public class JpaPageRepositoryTest {
 
     @Autowired
     private PageRepository repository;
-    
+
     @Autowired
     private UserRepository userRepository;
 
@@ -87,9 +88,10 @@ public class JpaPageRepositoryTest {
         assertThat(pages.get(0).getRegions().get(0).getRegionWidgets().size(), equalTo(2));
         assertThat(pages.get(0).getRegions().get(0).getRegionWidgets().get(0).getWidget().getUrl(), equalTo(WIDGET_URL));
         
+        List<PageUser> pageUserPages = repository.getPagesForUser(USER_ID, PageType.USER);
         // test that the query returns the pages in proper render sequence order
         Long lastRenderSequence = -1L;
-        for (Page p : pages) {
+        for (PageUser p : pageUserPages) {
             Long currentRenderSequence = p.getRenderSequence();
             assertThat(currentRenderSequence > lastRenderSequence, is(true));
             lastRenderSequence = currentRenderSequence;
@@ -103,9 +105,10 @@ public class JpaPageRepositoryTest {
         assertThat(pages.size(), is(1));
         assertThat(pages.get(0).getRegions().size(), is(1));
 
+        List<PageUser> pageUserPages = repository.getPagesForUser(USER_ID, PageType.PERSON_PROFILE);
         // test that the query returns the pages in proper render sequence order
         Long lastRenderSequence = -1L;
-        for (Page p : pages) {
+        for (PageUser p : pageUserPages) {
             Long currentRenderSequence = p.getRenderSequence();
             assertThat(currentRenderSequence > lastRenderSequence, is(true));
             lastRenderSequence = currentRenderSequence;
@@ -120,9 +123,10 @@ public class JpaPageRepositoryTest {
         assertThat(pages.get(0).getRegions().size(), is(1));
         assertThat(pages.get(0).getParentPage().getEntityId(), is(3L));
 
+        List<PageUser> pageUserPages = repository.getPagesForUser(USER_ID, PageType.SUB_PAGE);
         // test that the query returns the pages in proper render sequence order
         Long lastRenderSequence = -1L;
-        for (Page p : pages) {
+        for (PageUser p : pageUserPages) {
             Long currentRenderSequence = p.getRenderSequence();
             assertThat(currentRenderSequence > lastRenderSequence, is(true));
             lastRenderSequence = currentRenderSequence;
@@ -167,8 +171,10 @@ public class JpaPageRepositoryTest {
 
         // verify that the sub pages are in proper order
         Long lastRenderSequence = -1L;
+        PageUser pageUser;
         for (Page subPage : p.getSubPages()) {
-            Long currentRenderSequence = subPage.getRenderSequence();
+            pageUser = repository.getSingleRecord(p.getOwner().getEntityId(), subPage.getEntityId());
+            Long currentRenderSequence =  pageUser.getRenderSequence();
             assertThat(currentRenderSequence > lastRenderSequence, is(true));
             lastRenderSequence = currentRenderSequence;
         }
@@ -212,7 +218,6 @@ public class JpaPageRepositoryTest {
         assertEquals(page.getName(), defaultPageTemplate.getName());
         assertNull(page.getParentPage());
         assertEquals(2, page.getSubPages().size());
-        assertNotNull(page.getRenderSequence());
         assertNotNull(page.getPageLayout());
         assertEquals("person_profile", page.getPageLayout().getCode());
         assertEquals(1, page.getRegions().size());
@@ -237,8 +242,6 @@ public class JpaPageRepositoryTest {
         assertEquals(defaultPageTemplate.getSubPageTemplates().get(1).getName(), subPage2.getName());
         assertSame(user, subPage1.getOwner());
         assertSame(user, subPage2.getOwner());
-        assertNotNull(subPage1.getRenderSequence());
-        assertNotNull(subPage2.getRenderSequence());
     }
     
     @Test

Modified: rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultPageServiceTest.java
URL: http://svn.apache.org/viewvc/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultPageServiceTest.java?rev=1335687&r1=1335686&r2=1335687&view=diff
==============================================================================
--- rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultPageServiceTest.java (original)
+++ rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultPageServiceTest.java Tue May  8 18:50:10 2012
@@ -66,7 +66,10 @@ public class DefaultPageServiceTest {
     private PageLayout pageLayout;
     private String defaultPageName = "Main";
     private Page page, page2;
+    private PageUser pageUser, pageUser2;
     private List<Page> pageList;
+    private List<PageUser> pageUserList;
+    
 
     @Before
     public void setup() {
@@ -84,9 +87,14 @@ public class DefaultPageServiceTest {
         validWidget = new Widget(1L, "http://dummy.apache.org/widgets/widget.xml");
 
         page = new Page(PAGE_ID, user);
-        page.setRenderSequence(1L);
+        pageUser = new PageUser(user, page, 1L);
+        page.setMembers(new ArrayList<PageUser>());
+        page.getMembers().add(pageUser);
+        
         page2 = new Page(99L, user);
-        page2.setRenderSequence(2L);
+        pageUser2 = new PageUser(user, page2, 2L);
+        page2.setMembers(new ArrayList<PageUser>());
+        page2.getMembers().add(pageUser2);
 
         targetRegion = new Region();
         targetRegion.setEntityId(2L);
@@ -119,10 +127,14 @@ public class DefaultPageServiceTest {
         user.setUsername("acarlucci"); 
         user.setDefaultPageLayout(pageLayout);
         
-        pageList = new ArrayList<Page>();        
+        pageList = new ArrayList<Page>();
         pageList.add(page2);
         pageList.add(page);
 
+        pageUserList = new ArrayList<PageUser>();
+        pageUserList.add(pageUser);
+        pageUserList.add(pageUser2);
+
         validRegionWidget = new RegionWidget();
         validRegionWidget.setEntityId(VALID_REGION_WIDGET_ID);
         validRegionWidget.setWidget(validWidget);
@@ -183,9 +195,12 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);       
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));    
         expectedPage.setPageType(PageType.USER);
+        PageUser lPageUser = new PageUser(user, expectedPage, EXPECTED_RENDER_SEQUENCE);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(lPageUser);
+        expectedPage.setMembers(members);
 
         expect(userService.getAuthenticatedUser()).andReturn(user);
         expect(pageLayoutRepository.getByPageLayoutCode(PAGE_LAYOUT_CODE)).andReturn(pageLayout);
@@ -196,7 +211,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
 
         Page newPage = pageService.addNewUserPage(PAGE_NAME, PAGE_LAYOUT_CODE);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.USER));
@@ -204,7 +219,6 @@ public class DefaultPageServiceTest {
         verify(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
     }
 
-
     @Test
     public void addNewUserPage_noExistingPages_no_result_exception() {
         final String PAGE_NAME = "my new page";
@@ -214,7 +228,6 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
         expectedPage.setPageType(PageType.USER);
 
@@ -227,7 +240,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
 
         Page newPage = pageService.addNewUserPage(PAGE_NAME, PAGE_LAYOUT_CODE);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.USER));
@@ -244,7 +257,6 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
         expectedPage.setPageType(PageType.USER);
 
@@ -257,7 +269,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
 
         Page newPage = pageService.addNewUserPage(PAGE_NAME, PAGE_LAYOUT_CODE);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.USER));
@@ -278,9 +290,12 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
         expectedPage.setPageType(PageType.USER);
+        PageUser lPageUser = new PageUser(user, expectedPage, EXPECTED_RENDER_SEQUENCE);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(lPageUser);
+        userPage.setMembers(members);
 
         expect(userService.getAuthenticatedUser()).andReturn(user);
         expect(pageLayoutRepository.getByPageLayoutCode(PAGE_LAYOUT_CODE)).andReturn(pageLayout);
@@ -288,7 +303,10 @@ public class DefaultPageServiceTest {
         expect(pageRepository.createPageForUser(user, pageTemplate)).andReturn(userPage);
         expect(pageTemplateRepository.getDefaultPage(PageType.USER)).andReturn(pageTemplate);
         replay(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
+
         Page newPage = pageService.addNewUserPage(PAGE_NAME, PAGE_LAYOUT_CODE);
+
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is("Page Template"));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
 
@@ -304,11 +322,14 @@ public class DefaultPageServiceTest {
         existingPages.add(new Page());
                       
         Page expectedPage = new Page();
-        expectedPage.setName(PAGE_NAME);       
+        expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
-        expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));    
+        expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
+        PageUser lPageUser = new PageUser(user, expectedPage, EXPECTED_RENDER_SEQUENCE);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(lPageUser);
+        expectedPage.setMembers(members);
                 
         expect(userService.getAuthenticatedUser()).andReturn(user);
         expect(pageLayoutRepository.getByPageLayoutCode(PAGE_LAYOUT_CODE)).andReturn(pageLayout);       
@@ -317,7 +338,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository, pageRepository);
 
         Page newPage = pageService.addNewUserPage(PAGE_NAME, PAGE_LAYOUT_CODE);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.USER));
@@ -326,7 +347,7 @@ public class DefaultPageServiceTest {
             assertThat(region.isLocked(), is(false));
         }
 
-        verify(userService, pageLayoutRepository,  pageRepository);
+        verify(userService, pageLayoutRepository, pageRepository);
     }
 
     @Test
@@ -340,14 +361,13 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
 
         Page parentPage = new Page();
         parentPage.setName(PARENT_PAGE_NAME);
         parentPage.setOwner(user);
         parentPage.setPageLayout(pageLayout);
-        parentPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
+
         parentPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
 
         expect(userService.getAuthenticatedUser()).andReturn(user);
@@ -356,7 +376,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository,  pageRepository);
 
         Page newPage = pageService.addNewSubPage(PAGE_NAME, PAGE_LAYOUT_CODE, parentPage);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.SUB_PAGE));
@@ -378,14 +398,12 @@ public class DefaultPageServiceTest {
         expectedPage.setName(PAGE_NAME);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
 
         Page parentPage = new Page();
         parentPage.setName(PARENT_PAGE_NAME);
         parentPage.setOwner(user);
         parentPage.setPageLayout(pageLayout);
-        parentPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
         parentPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
         parentPage.setSubPages(existingPages);
 
@@ -395,7 +413,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository,  pageRepository);
 
         Page newPage = pageService.addNewSubPage(PAGE_NAME, PAGE_LAYOUT_CODE, parentPage);
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(PAGE_NAME));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         assertThat(newPage.getPageType(), is(PageType.SUB_PAGE));
@@ -407,14 +425,18 @@ public class DefaultPageServiceTest {
    
     @Test
     public void addNewDefaultUserPage() {
+        
         final Long EXPECTED_RENDER_SEQUENCE = 1L;
         PageTemplate pageTemplate = new PageTemplate();
         Page expectedPage = new Page();
-        expectedPage.setName(defaultPageName);       
+        expectedPage.setName(defaultPageName);
         expectedPage.setOwner(user);
         expectedPage.setPageLayout(pageLayout);
-        expectedPage.setRenderSequence(EXPECTED_RENDER_SEQUENCE);
-        expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));    
+        expectedPage.setRegions(createEmptyRegionList(pageLayout.getNumberOfRegions()));
+        PageUser lPageUser = new PageUser(user, expectedPage, EXPECTED_RENDER_SEQUENCE);
+        List<PageUser> members = new ArrayList<PageUser>();
+        members.add(lPageUser);
+        expectedPage.setMembers(members);
                 
         expect(userService.getUserById(user.getEntityId())).andReturn(user);
         expect(pageLayoutRepository.getByPageLayoutCode(PAGE_LAYOUT_CODE)).andReturn(pageLayout);
@@ -424,7 +446,7 @@ public class DefaultPageServiceTest {
         replay(userService, pageLayoutRepository, pageRepository, pageTemplateRepository);
 
         Page newPage = pageService.addNewDefaultUserPage(user.getEntityId());
-        assertThat(newPage.getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
+        assertThat(newPage.getMembers().get(0).getRenderSequence(), is(EXPECTED_RENDER_SEQUENCE));
         assertThat(newPage.getName(), is(defaultPageName));
         assertThat(newPage.getRegions().size(), is(pageLayout.getNumberOfRegions().intValue()));
         
@@ -438,15 +460,16 @@ public class DefaultPageServiceTest {
   
     @Test
     public void deletePage() {
-        List<Page> pageListAfterDelete = new ArrayList<Page>(pageList);
-        pageListAfterDelete.remove(page);
+        List<PageUser> pageUserListAfterDelete = new ArrayList<PageUser>(pageUserList);
+        pageUserListAfterDelete.remove(pageUser);
         
         expect(userService.getAuthenticatedUser()).andReturn(user);
         expect(pageRepository.get(PAGE_ID)).andReturn(page);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserListAfterDelete);
+        expect(pageRepository.save(page2)).andReturn(page2);
+
         pageRepository.delete(page);
         expectLastCall();
-        expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageListAfterDelete);
-        expect(pageRepository.save(page2)).andReturn(page2);
         replay(userService);
         replay(pageRepository);
         pageService.deletePage(PAGE_ID);
@@ -455,33 +478,34 @@ public class DefaultPageServiceTest {
     }
     
     @Test
-    public void deletePage_invalidId() {               
+    public void deletePage_invalidId() {
         final long INVALID_PAGE_ID = -999L;
-        
+        List<PageUser> pageUserListAfterDelete = new ArrayList<PageUser>(pageUserList);
+
         expect(userService.getAuthenticatedUser()).andReturn(user);
         expect(pageRepository.get(INVALID_PAGE_ID)).andReturn(page);
         pageRepository.delete(page);
         expectLastCall();
-        expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageList);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserListAfterDelete);
         expect(pageRepository.save(page2)).andReturn(page2);
         expect(pageRepository.save(page)).andReturn(page);
         replay(userService);
         replay(pageRepository);
+
         pageService.deletePage(INVALID_PAGE_ID);
         verify(userService);
         verify(pageRepository);
     }
 
     @Test
-    public void deletePages() {                      
+    public void deletePages() {
         final int EXPECTED_DELETED_PAGE_COUNT = 7;
         expect(pageRepository.deletePages(VALID_USER_ID, PageType.USER)).andReturn(EXPECTED_DELETED_PAGE_COUNT);     
         replay(pageRepository);
         assertThat(pageService.deletePages(VALID_USER_ID, PageType.USER), is(EXPECTED_DELETED_PAGE_COUNT));
         verify(pageRepository);
-    }    
-    
-    
+    }
+
     @Test
     public void moveRegionWidget_validMiddle() {
         final int newPosition = 0;
@@ -820,12 +844,12 @@ public class DefaultPageServiceTest {
     public void getPage() {
         expect(pageRepository.get(PAGE_ID)).andReturn(page);
         replay(pageRepository);
-          
+
         assertThat(pageService.getPage(PAGE_ID), is(page));
-        
+
         verify(pageRepository);
     }
-    
+
     @Test
     public void getPageFromList() {
         assertThat(pageService.getPageFromList(PAGE_ID, pageList), is(page));
@@ -852,79 +876,86 @@ public class DefaultPageServiceTest {
     }      
     
     @Test
-    public void movePage() {               
+    public void movePage() {
         expect(userService.getAuthenticatedUser()).andReturn(user);
-        expect(pageRepository.get(PAGE_ID)).andReturn(page);
-        expect(pageRepository.get(page2.getEntityId())).andReturn(page2);
-        expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageList);
-        expect(pageRepository.save(page2)).andReturn(page2);
-        expect(pageRepository.save(page)).andReturn(page);        
+        expect(pageRepository.getSingleRecord(user.getEntityId(), PAGE_ID)).andReturn(pageUser);
+        expect(pageRepository.getSingleRecord(user.getEntityId(), page2.getEntityId())).andReturn(pageUser2);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserList);
+
+        expect(pageRepository.save(page)).andReturn(page);
+        expect(pageRepository.save(page2)).andReturn(page);
         replay(userService);
         replay(pageRepository);
-                          
-        assertThat(pageService.movePage(PAGE_ID, page2.getEntityId()).getRenderSequence(), is(2L));
-        assertThat(page2.getRenderSequence(), is(1L));        
-      
-        verify(userService);        
+
+        Page p = pageService.movePage(PAGE_ID, page2.getEntityId());
+
+        assertThat(pageUser.getRenderSequence(), is(2L));
+        assertThat(pageUser2.getRenderSequence(), is(1L));
+
+        verify(userService);
         verify(pageRepository);
     }
-    
+
     @Test(expected=RuntimeException.class)
     public void movePage_invalidPageId() {               
         expect(userService.getAuthenticatedUser()).andReturn(user);
+        expect(pageRepository.getSingleRecord(user.getEntityId(), INVALID_PAGE_ID)).andReturn(null);
+        expect(pageRepository.getSingleRecord(user.getEntityId(), page2.getEntityId())).andReturn(pageUser2);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserList);
+
         expect(pageRepository.get(INVALID_PAGE_ID)).andReturn(null);
         expect(pageRepository.get(page2.getEntityId())).andReturn(page2);
         expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageList);
         replay(userService);
         replay(pageRepository);
-                          
+
         pageService.movePage(INVALID_PAGE_ID, page2.getEntityId());
-      
-        verify(userService);        
+
+        verify(userService);
         verify(pageRepository);
-    }    
-  
+    }
+
     @Test
-    public void movePageToDefault() {               
+    public void movePageToDefault() {
         expect(userService.getAuthenticatedUser()).andReturn(user);
-        expect(pageRepository.get(page2.getEntityId())).andReturn(page2);
-        expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageList);
+        expect(pageRepository.getSingleRecord(user.getEntityId(), page2.getEntityId())).andReturn(pageUser2);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserList);
         expect(pageRepository.save(page)).andReturn(page);
-        expect(pageRepository.save(page2)).andReturn(page2);        
+        expect(pageRepository.save(page2)).andReturn(page);
         replay(userService);
         replay(pageRepository);
-                          
-        assertThat(pageService.movePageToDefault(page2.getEntityId()).getRenderSequence(), is(1L));
-        assertThat(page.getRenderSequence(), is(2L));        
-      
-        verify(userService);        
+
+        pageService.movePageToDefault(page2.getEntityId());
+        assertThat(pageUser2.getRenderSequence(), is(1L));
+        assertThat(pageUser.getRenderSequence(), is(2L));
+
+        verify(userService);
         verify(pageRepository);
-    }    
-    
+    }
+
     @Test(expected=RuntimeException.class)
     public void movePageToDefault_invalidPageId() {               
         expect(userService.getAuthenticatedUser()).andReturn(user);
-        expect(pageRepository.get(INVALID_PAGE_ID)).andReturn(null);
-        expect(pageRepository.getAllPages(user.getEntityId(), PageType.USER)).andReturn(pageList);
+        expect(pageRepository.getSingleRecord(user.getEntityId(), INVALID_PAGE_ID)).andReturn(null);
+        expect(pageRepository.getPagesForUser(user.getEntityId(), PageType.USER)).andReturn(pageUserList);
         replay(userService);
         replay(pageRepository);
-                          
-        pageService.movePageToDefault(INVALID_PAGE_ID);     
-      
-        verify(userService);        
+
+        pageService.movePageToDefault(INVALID_PAGE_ID);
+
+        verify(userService);
         verify(pageRepository);
     }
-    
+
     @Test
     public void updatePage_nameUpdate() {
         String newName = "new page name";
         String layoutName = "layout name";
-        
+
         PageLayout layout = createStrictMock(PageLayout.class);
         expect(layout.getNumberOfRegions()).andReturn(new Long(2)).anyTimes();
-//        expect(layout.equals(layout)).andReturn((boolean) true);
         replay(layout);
-        
+
         //create a strict mock that ensures that the appropriate setters are
         //called, rather than checking the return value from the function
         Page curPage = createStrictMock(Page.class);
@@ -932,42 +963,40 @@ public class DefaultPageServiceTest {
         curPage.setName(newName);
         curPage.setPageLayout(layout);
         replay(curPage);
-        
+
         expect(pageRepository.get(PAGE_ID)).andReturn(curPage);
         expect(pageRepository.save(curPage)).andReturn(curPage);
         replay(pageRepository);
-        
-        
+
         expect(pageLayoutRepository.getByPageLayoutCode(layoutName)).andReturn(layout);
         replay(pageLayoutRepository);
-        
+
         pageService.updatePage(PAGE_ID, newName, layoutName);
-        
+
         verify(curPage);
     }
-    
-    
+
     @Test
     public void updatePage_addRegion() {
         String newName = "new page name";
         String layoutName = "layout name";
-        
+
         List<Region> regions = new ArrayList<Region>();
         Region region = createStrictMock(Region.class);
         expect(region.getRenderOrder()).andReturn(1);
         replay(region);
         regions.add(new Region());
         regions.add(region);
-        
+
         PageLayout prevLayout = createStrictMock(PageLayout.class);
         expect(prevLayout.getNumberOfRegions()).andReturn(new Long(2)).anyTimes();
         replay(prevLayout);
         
         PageLayout layout = createStrictMock(PageLayout.class);
         expect(layout.getNumberOfRegions()).andReturn(new Long(3)).anyTimes();
-//        expect(layout.equals(layout)).andReturn((boolean) true);
+        //expect(layout.equals(layout)).andReturn((boolean) true);
         replay(layout);
-        
+
         //create a strict mock that ensures that the appropriate setters are
         //called, rather than checking the return value from the function
         Page curPage = createStrictMock(Page.class);
@@ -976,18 +1005,18 @@ public class DefaultPageServiceTest {
         curPage.setName(newName);
         curPage.setPageLayout(layout);
         replay(curPage);
-        
+
         expect(pageRepository.get(PAGE_ID)).andReturn(curPage);
         expect(pageRepository.save(curPage)).andReturn(curPage);
         replay(pageRepository);
-        
+
         expect(pageLayoutRepository.getByPageLayoutCode(layoutName)).andReturn(layout);
         replay(pageLayoutRepository);
-        
+
         pageService.updatePage(PAGE_ID, newName, layoutName);
         assertThat(regions.size(), is(3));
         assertThat(regions.get(regions.size()-1).getPage(), is(curPage));
-        
+
         verify(curPage);
     }