TAPESTRY-2665: Many methods of the Page interface could be moved to PageResources (which should be renamed to ComponentPageElementResources)

git-svn-id: https://svn.apache.org/repos/asf/tapestry/tapestry5/branches/5.1-dev@696339 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResources.java b/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResources.java
index 587a90f..bac44d6 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResources.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResources.java
@@ -162,74 +162,6 @@
 
 
     /**
-     * Creates a component event request link as a callback for this component. The event type and context (as well as
-     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
-     * #triggerEvent(String, Object[], ComponentEventCallback)}  trigger} the named event on the component.
-     *
-     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
-     *                  letters, numbers and the underscore).
-     * @param forForm   if true, the link will be used as the eventType for an HTML form submission, which may affect
-     *                  what information is encoded into the link
-     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
-     *                  string and URI encoded
-     * @return link object for the callback
-     * @deprecated Use {@link #createEventLink(String, Object[])} instead
-     */
-    Link createActionLink(String eventType, boolean forForm, Object... context);
-
-    /**
-     * Creates a component event request link as a callback for this component. The event type and context (as well as
-     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
-     * #triggerEvent(String, Object[], ComponentEventCallback)}  trigger} the named event on the component.
-     *
-     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
-     *                  letters, numbers and the underscore).
-     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
-     *                  string and URI encoded
-     * @return link object for the callback
-     */
-    Link createEventLink(String eventType, Object... context);
-
-    /**
-     * Creates a component event request link as a callback for this component. The event type and context (as well as
-     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
-     * #triggerEvent(String, Object[], ComponentEventCallback)}  trigger} the named event on the component. This is only
-     * used for form submission events, as extra data may be encoded in the form as hidden fields.
-     *
-     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
-     *                  letters, numbers and the underscore).
-     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
-     *                  string and URI encoded
-     * @return link object for the callback
-     */
-    Link createFormEventLink(String eventType, Object... context);
-
-    /**
-     * Creates a page render request link to render a specific page.
-     *
-     * @param pageName the logical name of the page to link to
-     * @param override if true, the context is used even if empty (normally, the target page is allowed to passivate,
-     *                 providing a context, when the provided context is empty)
-     * @param context  the activation context for the page. If omitted, the activation context is obtained from the
-     *                 target page
-     * @return link for a render request to the targetted page
-     */
-    Link createPageLink(String pageName, boolean override, Object... context);
-
-    /**
-     * Creates a page render request link to render a specific page. Using a page class, rather than a page name, is
-     * more refactoring safe (in the even the page is renamed or moved).
-     *
-     * @param pageClass identifies the page to link to
-     * @param override  if true, the context is used even if empty (normally, the target page is allowed to passivate,
-     *                  providing a context, when the provided context is empty)
-     * @param context   the activation context for the page. If omitted, the activation context is obtained from the
-     *                  target page
-     * @return link for a render request to the targetted page
-     */
-    Link createPageLink(Class pageClass, boolean override, Object... context);
-
-    /**
      * Discards all persistent field changes for the page containing the component.  Changes are eliminated from
      * persistent storage (such as the {@link org.apache.tapestry5.services.Session}) which will take effect in the
      * <em>next</em> request (the attached page instance is not affected).
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java b/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java
index c77ec76..e203f8c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java
@@ -155,4 +155,75 @@
      * component's body.
      */
     Block getBody();
+
+    /**
+     * Creates a component event request link as a callback for this component. The event type and context (as well as
+     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
+     * #triggerEvent(String, Object[], org.apache.tapestry5.ComponentEventCallback)}  trigger} the named event on the
+     * component.
+     *
+     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
+     *                  letters, numbers and the underscore).
+     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
+     *                  string and URI encoded
+     * @return link object for the callback
+     */
+    Link createEventLink(String eventType, Object... context);
+
+    /**
+     * Creates a component event request link as a callback for this component. The event type and context (as well as
+     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
+     * #triggerEvent(String, Object[], org.apache.tapestry5.ComponentEventCallback)}  trigger} the named event on the
+     * component.
+     *
+     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
+     *                  letters, numbers and the underscore).
+     * @param forForm   if true, the link will be used as the eventType for an HTML form submission, which may affect
+     *                  what information is encoded into the link
+     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
+     *                  string and URI encoded
+     * @return link object for the callback
+     * @deprecated Use {@link #createEventLink(String, Object[])} instead
+     */
+    Link createActionLink(String eventType, boolean forForm, Object... context);
+
+    /**
+     * Creates a component event request link as a callback for this component. The event type and context (as well as
+     * the page name and nested component id) will be encoded into a URL. A request for the URL will {@linkplain
+     * #triggerEvent(String, Object[], org.apache.tapestry5.ComponentEventCallback)}  trigger} the named event on the
+     * component. This is only used for form submission events, as extra data may be encoded in the form as hidden
+     * fields.
+     *
+     * @param eventType the type of event to be triggered.  Event types should be Java identifiers (contain only
+     *                  letters, numbers and the underscore).
+     * @param context   additional objects to be encoded into the path portion of the link; each is converted to a
+     *                  string and URI encoded
+     * @return link object for the callback
+     */
+    Link createFormEventLink(String eventType, Object... context);
+
+    /**
+     * Creates a page render request link to render a specific page.
+     *
+     * @param pageName the logical name of the page to link to
+     * @param override if true, the context is used even if empty (normally, the target page is allowed to passivate,
+     *                 providing a context, when the provided context is empty)
+     * @param context  the activation context for the page. If omitted, the activation context is obtained from the
+     *                 target page
+     * @return link for a render request to the targetted page
+     */
+    Link createPageLink(String pageName, boolean override, Object... context);
+
+    /**
+     * Creates a page render request link to render a specific page. Using a page class, rather than a page name, is
+     * more refactoring safe (in the even the page is renamed or moved).
+     *
+     * @param pageClass identifies the page to link to
+     * @param override  if true, the context is used even if empty (normally, the target page is allowed to passivate,
+     *                  providing a context, when the provided context is empty)
+     * @param context   the activation context for the page. If omitted, the activation context is obtained from the
+     *                  target page
+     * @return link for a render request to the targetted page
+     */
+    Link createPageLink(Class pageClass, boolean override, Object... context);
 }
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventImpl.java
index 845612d..318df26 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventImpl.java
@@ -16,7 +16,7 @@
 
 import org.apache.tapestry5.ComponentEventCallback;
 import org.apache.tapestry5.EventContext;
-import org.apache.tapestry5.internal.structure.PageResources;
+import org.apache.tapestry5.internal.structure.ComponentPageElementResources;
 import org.apache.tapestry5.runtime.ComponentEvent;
 import org.slf4j.Logger;
 
@@ -28,24 +28,26 @@
 
     private final EventContext context;
 
-    private final PageResources pageResources;
+    private final ComponentPageElementResources componentPageElementResources;
 
     /**
-     * @param eventType              non blank string used to identify the type of event that was triggered
-     * @param originatingComponentId the id of the component that triggered the event
-     * @param context                provides access to parameter values
-     * @param handler                invoked when a non-null return value is obtained from an event handler method
-     * @param pageResources          provides access to common resources and services
-     * @param logger                 used to log method invocations
+     * @param eventType                     non blank string used to identify the type of event that was triggered
+     * @param originatingComponentId        the id of the component that triggered the event
+     * @param context                       provides access to parameter values
+     * @param handler                       invoked when a non-null return value is obtained from an event handler
+     *                                      method
+     * @param componentPageElementResources provides access to common resources and services
+     * @param logger                        used to log method invocations
      */
     public ComponentEventImpl(String eventType, String originatingComponentId, EventContext context,
-                              ComponentEventCallback handler, PageResources pageResources, Logger logger)
+                              ComponentEventCallback handler,
+                              ComponentPageElementResources componentPageElementResources, Logger logger)
     {
         super(handler, logger);
 
         this.eventType = eventType;
         this.originatingComponentId = originatingComponentId;
-        this.pageResources = pageResources;
+        this.componentPageElementResources = componentPageElementResources;
         this.context = context;
     }
 
@@ -71,10 +73,9 @@
                 .contextIndexOutOfRange(getMethodDescription()));
         try
         {
-            Class desiredType = pageResources.toClass(desiredTypeName);
+            Class desiredType = componentPageElementResources.toClass(desiredTypeName);
 
             return context.get(desiredType, index);
-
         }
         catch (Exception ex)
         {
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
index dcc82f9..edf95b7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
@@ -15,8 +15,8 @@
 package org.apache.tapestry5.internal.services;
 
 import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.internal.structure.PageResourcesSource;
-import org.apache.tapestry5.internal.structure.PageResourcesSourceImpl;
+import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
+import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSourceImpl;
 import static org.apache.tapestry5.ioc.IOCConstants.PERTHREAD_SCOPE;
 import org.apache.tapestry5.ioc.ObjectLocator;
 import org.apache.tapestry5.ioc.ServiceBinder;
@@ -80,7 +80,7 @@
         binder.bind(AjaxPartialResponseRenderer.class, AjaxPartialResponseRendererImpl.class);
         binder.bind(PageContentTypeAnalyzer.class, PageContentTypeAnalyzerImpl.class);
         binder.bind(RequestPathOptimizer.class, RequestPathOptimizerImpl.class);
-        binder.bind(PageResourcesSource.class, PageResourcesSourceImpl.class);
+        binder.bind(ComponentPageElementResourcesSource.class, ComponentPageElementResourcesSourceImpl.class);
         binder.bind(RequestSecurityManager.class, RequestSecurityManagerImpl.class);
         binder.bind(InternalRequestGlobals.class, InternalRequestGlobalsImpl.class);
         binder.bind(EndOfRequestListenerHub.class);
@@ -216,7 +216,6 @@
             {
                 requestGlobals.getHTTPServletResponse().addCookie(cookie);
             }
-
         };
     }
 
@@ -256,5 +255,4 @@
     {
         return builder.build(componentInstantiatorSource, "classSource", CtClassSource.class);
     }
-
 }
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactory.java
index 465d985..1fd2a44 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactory.java
@@ -18,7 +18,7 @@
 import org.apache.tapestry5.internal.structure.Page;
 
 /**
- * A source for {@link Link} objects.
+ * A source for {@link org.apache.tapestry5.Link} objects.
  *
  * @see LinkFactoryListener
  */
@@ -57,14 +57,14 @@
 
     /**
      * As with {@link #createPageRenderLink(Page, boolean, Object[])}, but the page is specified by logical name, rather
-     * than as an instance.
+     * than as an instance.  Note: renamed from createPageLink() in 5.1.
      *
      * @param logicalPageName the logical name of the page to generate a link to
      * @param override        if true, then the provided activation context is always used even if empty
      * @param context         activation context for the page
-     * @return
+     * @return a link
      */
-    Link createPageLink(String logicalPageName, boolean override, Object... context);
+    Link createPageRenderLink(String logicalPageName, boolean override, Object... context);
 
     /**
      * Adds a listener, to be notified any time an action or render link is created; this allows the listener to modify
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java
index e6f3306..4d5e241 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java
@@ -268,7 +268,7 @@
         return result;
     }
 
-    public Link createPageLink(String logicalPageName, boolean override, Object... context)
+    public Link createPageRenderLink(String logicalPageName, boolean override, Object... context)
     {
         // This verifies that the page name is valid.
         Page page = pageCache.get(logicalPageName);
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java
index 942da47..22b9412 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java
@@ -44,7 +44,7 @@
 
     private final BindingSource bindingSource;
 
-    private final PageResourcesSource pageResourcesSource;
+    private final ComponentPageElementResourcesSource componentPageElementResourcesSource;
 
     private static final String EXPANSION_START = "${";
 
@@ -65,13 +65,13 @@
 
     public PageElementFactoryImpl(ComponentInstantiatorSource componentInstantiatorSource,
                                   ComponentClassResolver resolver, TypeCoercer typeCoercer, BindingSource bindingSource,
-                                  PageResourcesSource pageResourcesSource)
+                                  ComponentPageElementResourcesSource componentPageElementResourcesSource)
     {
         this.componentInstantiatorSource = componentInstantiatorSource;
         componentClassResolver = resolver;
         this.typeCoercer = typeCoercer;
         this.bindingSource = bindingSource;
-        this.pageResourcesSource = pageResourcesSource;
+        this.componentPageElementResourcesSource = componentPageElementResourcesSource;
     }
 
     public PageElement newAttributeElement(ComponentResources componentResources, AttributeToken token)
@@ -168,7 +168,6 @@
                 return builder.toString();
             }
         };
-
     }
 
     public PageElement newExpansionElement(ComponentResources componentResources, ExpansionToken token)
@@ -256,9 +255,9 @@
     {
         Instantiator instantiator = componentInstantiatorSource.findInstantiator(componentType);
 
-        PageResources pageResources = pageResourcesSource.get(locale);
+        ComponentPageElementResources componentPageElementResources = componentPageElementResourcesSource.get(locale);
 
-        ComponentPageElement result = new ComponentPageElementImpl(page, instantiator, pageResources);
+        ComponentPageElement result = new ComponentPageElementImpl(page, instantiator, componentPageElementResources);
 
         page.addLifecycleListener(result);
 
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderImpl.java
index fb22f2e..266a9e6 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderImpl.java
@@ -28,19 +28,16 @@
 
     private final PageElementFactory pageElementFactory;
 
-    private final LinkFactory linkFactory;
-
     private final PersistentFieldManager persistentFieldManager;
 
     private final ComponentClassResolver componentClassResolver;
 
     public PageLoaderImpl(ComponentTemplateSource templateSource,
-                          PageElementFactory pageElementFactory, LinkFactory linkFactory,
+                          PageElementFactory pageElementFactory,
                           PersistentFieldManager persistentFieldManager, ComponentClassResolver componentClassResolver)
     {
         this.templateSource = templateSource;
         this.pageElementFactory = pageElementFactory;
-        this.linkFactory = linkFactory;
         this.persistentFieldManager = persistentFieldManager;
         this.componentClassResolver = componentClassResolver;
     }
@@ -51,8 +48,8 @@
         // effort to pool them for reuse, but not too likely.
 
         PageLoaderProcessor processor = new PageLoaderProcessor(templateSource,
-                                                                pageElementFactory, linkFactory,
-                                                                persistentFieldManager, componentClassResolver);
+                                                                pageElementFactory,
+                                                                persistentFieldManager);
 
         String pageClassName = componentClassResolver.resolvePageNameToClassName(logicalPageName);
 
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java
index 1269bfd..8e52675 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java
@@ -35,7 +35,6 @@
 import org.apache.tapestry5.model.EmbeddedComponentModel;
 import org.apache.tapestry5.runtime.RenderQueue;
 import org.apache.tapestry5.services.BindingSource;
-import org.apache.tapestry5.services.ComponentClassResolver;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -89,10 +88,6 @@
 
     private final IdAllocator idAllocator = new IdAllocator();
 
-    private final LinkFactory linkFactory;
-
-    private final ComponentClassResolver componentClassResolver;
-
     private ComponentModel loadingComponentModel;
 
     private ComponentPageElement loadingElement;
@@ -147,14 +142,11 @@
     }
 
     PageLoaderProcessor(ComponentTemplateSource templateSource, PageElementFactory pageElementFactory,
-                        LinkFactory linkFactory, PersistentFieldManager persistentFieldManager,
-                        ComponentClassResolver componentClassResolver)
+                        PersistentFieldManager persistentFieldManager)
     {
         this.templateSource = templateSource;
         this.pageElementFactory = pageElementFactory;
-        this.linkFactory = linkFactory;
         this.persistentFieldManager = persistentFieldManager;
-        this.componentClassResolver = componentClassResolver;
     }
 
     private void bindParameterFromTemplate(ComponentPageElement component, AttributeToken token)
@@ -394,7 +386,7 @@
         // Todo: Need a resources object for Pages, not just ComponentPageElement ... too many
         // parameters here.
 
-        page = new PageImpl(logicalPageName, this.locale, linkFactory, persistentFieldManager, componentClassResolver);
+        page = new PageImpl(logicalPageName, this.locale, persistentFieldManager);
 
         loadRootComponent(pageClassName);
 
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
index c4e9328..78ce406 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
@@ -376,7 +376,7 @@
 
     private final String elementName;
 
-    private final PageResources pageResources;
+    private final ComponentPageElementResources componentPageElementResources;
 
     private final Logger logger;
 
@@ -516,7 +516,7 @@
     public ComponentPageElement newChild(String id, String elementName, Instantiator instantiator, Location location)
     {
         ComponentPageElementImpl child = new ComponentPageElementImpl(page, this, id, elementName, instantiator,
-                                                                      location, pageResources);
+                                                                      location, componentPageElementResources);
 
         addEmbeddedElement(child);
 
@@ -526,18 +526,22 @@
     /**
      * Constructor for other components embedded within the root component or at deeper levels of the hierarchy.
      *
-     * @param page          ultimately containing this component
-     * @param container     component immediately containing this component (may be null for a root component)
-     * @param id            unique (within the container) id for this component (may be null for a root component)
-     * @param elementName   the name of the element which represents this component in the template, or null for
-     *                      &lt;comp&gt; element or a page component
-     * @param instantiator  used to create the new component instance and access the component's model
-     * @param location      location of the element (within a template), used as part of exception reporting
-     * @param pageResources Provides access to common methods of various services
+     * @param page                          ultimately containing this component
+     * @param container                     component immediately containing this component (may be null for a root
+     *                                      component)
+     * @param id                            unique (within the container) id for this component (may be null for a root
+     *                                      component)
+     * @param elementName                   the name of the element which represents this component in the template, or
+     *                                      null for &lt;comp&gt; element or a page component
+     * @param instantiator                  used to create the new component instance and access the component's model
+     * @param location                      location of the element (within a template), used as part of exception
+     *                                      reporting
+     * @param componentPageElementResources Provides access to common methods of various services
      */
 
     ComponentPageElementImpl(Page page, ComponentPageElement container, String id, String elementName,
-                             Instantiator instantiator, Location location, PageResources pageResources)
+                             Instantiator instantiator, Location location,
+                             ComponentPageElementResources componentPageElementResources)
     {
         super(location);
 
@@ -545,7 +549,7 @@
         this.container = container;
         this.id = id;
         this.elementName = elementName;
-        this.pageResources = pageResources;
+        this.componentPageElementResources = componentPageElementResources;
 
         ComponentResources containerResources = container == null
                                                 ? null
@@ -581,7 +585,8 @@
             }
         }
 
-        coreResources = new InternalComponentResourcesImpl(this.page, this, containerResources, this.pageResources,
+        coreResources = new InternalComponentResourcesImpl(this.page, this, containerResources,
+                                                           this.componentPageElementResources,
                                                            completeId, nestedId, instantiator);
 
         coreComponent = coreResources.getComponent();
@@ -592,9 +597,10 @@
     /**
      * Constructor for the root component of a page.
      */
-    public ComponentPageElementImpl(Page page, Instantiator instantiator, PageResources pageResources)
+    public ComponentPageElementImpl(Page page, Instantiator instantiator,
+                                    ComponentPageElementResources componentPageElementResources)
     {
-        this(page, null, null, null, instantiator, null, pageResources);
+        this(page, null, null, null, instantiator, null, componentPageElementResources);
     }
 
     public void addEmbeddedElement(ComponentPageElement child)
@@ -624,7 +630,7 @@
         String mixinExtension = "$" + mixinName.toLowerCase();
 
         InternalComponentResourcesImpl resources = new InternalComponentResourcesImpl(page, this, coreResources,
-                                                                                      pageResources,
+                                                                                      componentPageElementResources,
                                                                                       completeId + mixinExtension,
                                                                                       nestedId + mixinExtension,
                                                                                       instantiator);
@@ -989,7 +995,7 @@
 
             public <T> T get(Class<T> desiredType, int index)
             {
-                return pageResources.coerce(values[index], desiredType);
+                return componentPageElementResources.coerce(values[index], desiredType);
             }
         };
     }
@@ -1042,7 +1048,7 @@
                 Logger logger = component.getLogger();
 
                 ComponentEvent event = new ComponentEventImpl(currentEventType, componentId, currentContext, wrapped,
-                                                              pageResources, logger);
+                                                              componentPageElementResources, logger);
 
                 logger.debug(TapestryMarkers.EVENT_DISPATCH, "Dispatch event: {}", event);
 
@@ -1202,4 +1208,29 @@
     {
         return coreResources.getInformalParameterBindings();
     }
+
+    public Link createEventLink(String eventType, Object... context)
+    {
+        return componentPageElementResources.createComponentEventLink(coreResources, eventType, false, context);
+    }
+
+    public Link createActionLink(String eventType, boolean forForm, Object... context)
+    {
+        return componentPageElementResources.createComponentEventLink(coreResources, eventType, forForm, context);
+    }
+
+    public Link createFormEventLink(String eventType, Object... context)
+    {
+        return componentPageElementResources.createComponentEventLink(coreResources, eventType, true, context);
+    }
+
+    public Link createPageLink(String pageName, boolean override, Object... context)
+    {
+        return componentPageElementResources.createPageRenderLink(pageName, override, context);
+    }
+
+    public Link createPageLink(Class pageClass, boolean override, Object... context)
+    {
+        return componentPageElementResources.createPageRenderLink(pageClass, override, context);
+    }
 }
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java
new file mode 100644
index 0000000..e075ea5
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java
@@ -0,0 +1,102 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.structure;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.model.ComponentModel;
+import org.apache.tapestry5.services.ContextValueEncoder;
+
+/**
+ * Provides access to common methods of various services, needed by implementations of {@link ComponentPageElement} and
+ * {@link org.apache.tapestry5.internal.InternalComponentResources}.
+ */
+public interface ComponentPageElementResources extends ContextValueEncoder
+{
+    /**
+     * Used to obtain a {@link org.apache.tapestry5.ioc.Messages} instance for a particular component. If the component
+     * extends from another component, then its localized properties will merge with its parent's properties (with the
+     * subclass overriding the super class on any conflicts).
+     *
+     * @param componentModel
+     * @return the message catalog for the component, in the indicated locale
+     * @see org.apache.tapestry5.internal.services.ComponentMessagesSource
+     */
+    Messages getMessages(ComponentModel componentModel);
+
+    /**
+     * Performs a coercion from an input type to a desired output type. When the target type is a primitive, the actual
+     * conversion will be to the equivalent wrapper type. In some cases, the TypeCoercer will need to search for an
+     * appropriate coercion, and may even combine existing coercions to form new ones; in those cases, the results of
+     * the search are cached.
+     *
+     * @param <S>        source type (input)
+     * @param <T>        target type (output)
+     * @param input
+     * @param targetType defines the target type
+     * @return the coerced value
+     * @see org.apache.tapestry5.ioc.services.TypeCoercer
+     */
+    <S, T> T coerce(S input, Class<T> targetType);
+
+    /**
+     * Gets the Class instance for then give name.
+     *
+     * @param className fully qualified class name
+     * @return the class instance
+     * @see org.apache.tapestry5.internal.services.ComponentClassCache
+     */
+    Class toClass(String className);
+
+    /**
+     * Creates a link on behalf of a component.
+     *
+     * @param resources resources for the component
+     * @param eventType type of event to create
+     * @param forForm   true if generating for a form submission
+     * @param context   additional event context associated with the link
+     * @return the link
+     * @since 5.1
+     */
+    Link createComponentEventLink(ComponentResources resources, String eventType, boolean forForm, Object... context);
+
+    /**
+     * Creates a page render request link to render a specific page.
+     *
+     * @param pageName the logical name of the page to link to
+     * @param override if true, the context is used even if empty (normally, the target page is allowed to passivate,
+     *                 providing a context, when the provided context is empty)
+     * @param context  the activation context for the page. If omitted, the activation context is obtained from the
+     *                 target page
+     * @return link for a render request to the targetted page
+     * @since 5.1
+     */
+    Link createPageRenderLink(String pageName, boolean override, Object... context);
+
+    /**
+     * Creates a page render request link to render a specific page. Using a page class, rather than a page name, is
+     * more refactoring safe (in the even the page is renamed or moved).
+     *
+     * @param pageClass identifies the page to link to
+     * @param override  if true, the context is used even if empty (normally, the target page is allowed to passivate,
+     *                  providing a context, when the provided context is empty)
+     * @param context   the activation context for the page. If omitted, the activation context is obtained from the
+     *                  target page
+     * @return link for a render request to the targetted page
+     * @since 5.1
+     */
+    Link createPageRenderLink(Class pageClass, boolean override, Object... context);
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java
new file mode 100644
index 0000000..14b2378
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java
@@ -0,0 +1,113 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.structure;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.internal.services.ComponentClassCache;
+import org.apache.tapestry5.internal.services.ComponentMessagesSource;
+import org.apache.tapestry5.internal.services.LinkFactory;
+import org.apache.tapestry5.internal.services.RequestPageCache;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.internal.util.Defense;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.model.ComponentModel;
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.ContextValueEncoder;
+
+import java.util.Locale;
+
+public class ComponentPageElementResourcesImpl implements ComponentPageElementResources
+{
+    private final Locale locale;
+
+    private final ComponentMessagesSource componentMessagesSource;
+
+    private final TypeCoercer typeCoercer;
+
+    private final ComponentClassCache componentClassCache;
+
+    private final ContextValueEncoder contextValueEncoder;
+
+    private final LinkFactory linkFactory;
+
+    private final RequestPageCache requestPageCache;
+
+    private final ComponentClassResolver componentClassResolver;
+
+    public ComponentPageElementResourcesImpl(Locale locale, ComponentMessagesSource componentMessagesSource,
+                                             TypeCoercer typeCoercer,
+                                             ComponentClassCache componentClassCache,
+                                             ContextValueEncoder contextValueEncoder, LinkFactory linkFactory,
+                                             RequestPageCache requestPageCache,
+                                             ComponentClassResolver componentClassResolver)
+    {
+        this.componentMessagesSource = componentMessagesSource;
+        this.locale = locale;
+        this.typeCoercer = typeCoercer;
+        this.componentClassCache = componentClassCache;
+        this.contextValueEncoder = contextValueEncoder;
+        this.linkFactory = linkFactory;
+        this.requestPageCache = requestPageCache;
+        this.componentClassResolver = componentClassResolver;
+    }
+
+    public Messages getMessages(ComponentModel componentModel)
+    {
+        return componentMessagesSource.getMessages(componentModel, locale);
+    }
+
+    public <S, T> T coerce(S input, Class<T> targetType)
+    {
+        return typeCoercer.coerce(input, targetType);
+    }
+
+    public Class toClass(String className)
+    {
+        return componentClassCache.forName(className);
+    }
+
+    public Link createComponentEventLink(ComponentResources resources, String eventType, boolean forForm,
+                                         Object... context)
+    {
+        Page page = requestPageCache.get(resources.getPageName());
+
+        return linkFactory.createComponentEventLink(page, resources.getNestedId(), eventType, forForm, context);
+    }
+
+    public Link createPageRenderLink(String pageName, boolean override, Object... context)
+    {
+        return linkFactory.createPageRenderLink(pageName, override, context);
+    }
+
+    public Link createPageRenderLink(Class pageClass, boolean override, Object... context)
+    {
+        Defense.notNull(pageClass, "pageClass");
+
+        String pageName = componentClassResolver.resolvePageClassNameToPageName(pageClass.getName());
+
+        return linkFactory.createPageRenderLink(pageName, override, context);
+    }
+
+    public String toClient(Object value)
+    {
+        return contextValueEncoder.toClient(value);
+    }
+
+    public <T> T toValue(Class<T> requiredType, String clientValue)
+    {
+        return contextValueEncoder.toValue(requiredType, clientValue);
+    }
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSource.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSource.java
new file mode 100644
index 0000000..d7ff7a2
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSource.java
@@ -0,0 +1,31 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.structure;
+
+import java.util.Locale;
+
+/**
+ * Provides access to the {@link org.apache.tapestry5.internal.structure.ComponentPageElementResources} facade.
+ */
+public interface ComponentPageElementResourcesSource
+{
+    /**
+     * Gets (or creates) an instance of {@link ComponentPageElementResources} for the indicated locale.
+     *
+     * @param locale to create the resources for
+     * @return the resources
+     */
+    ComponentPageElementResources get(Locale locale);
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java
new file mode 100644
index 0000000..11550fe
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java
@@ -0,0 +1,85 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.structure;
+
+import org.apache.tapestry5.internal.services.ComponentClassCache;
+import org.apache.tapestry5.internal.services.ComponentMessagesSource;
+import org.apache.tapestry5.internal.services.LinkFactory;
+import org.apache.tapestry5.internal.services.RequestPageCache;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.internal.util.Defense;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.ContextValueEncoder;
+
+import java.util.Locale;
+import java.util.Map;
+
+public class ComponentPageElementResourcesSourceImpl implements ComponentPageElementResourcesSource
+{
+    private final Map<Locale, ComponentPageElementResources> cache = CollectionFactory.newConcurrentMap();
+
+    private final ComponentMessagesSource componentMessagesSource;
+
+    private final TypeCoercer typeCoercer;
+
+    private final ComponentClassCache componentClassCache;
+
+    private final ContextValueEncoder contextValueEncoder;
+
+    private final LinkFactory linkFactory;
+
+    private final RequestPageCache requestPageCache;
+
+    private final ComponentClassResolver componentClassResolver;
+
+    public ComponentPageElementResourcesSourceImpl(ComponentMessagesSource componentMessagesSource,
+                                                   TypeCoercer typeCoercer,
+                                                   ComponentClassCache componentClassCache,
+                                                   ContextValueEncoder contextValueEncoder, LinkFactory linkFactory,
+                                                   RequestPageCache requestPageCache,
+                                                   ComponentClassResolver componentClassResolver)
+    {
+        this.componentMessagesSource = componentMessagesSource;
+        this.typeCoercer = typeCoercer;
+        this.componentClassCache = componentClassCache;
+        this.contextValueEncoder = contextValueEncoder;
+        this.linkFactory = linkFactory;
+        this.requestPageCache = requestPageCache;
+        this.componentClassResolver = componentClassResolver;
+    }
+
+    public ComponentPageElementResources get(Locale locale)
+    {
+        Defense.notNull(locale, "locale");
+
+        ComponentPageElementResources result = cache.get(locale);
+
+        if (result == null)
+        {
+            result = new ComponentPageElementResourcesImpl(locale, componentMessagesSource, typeCoercer,
+                                                           componentClassCache,
+                                                           contextValueEncoder, linkFactory, requestPageCache,
+                                                           componentClassResolver);
+
+            // Small race condition here, where we may create two instances of the CPER for the same locale,
+            // but that's not worth worrying about.
+
+            cache.put(locale, result);
+        }
+
+        return result;
+    }
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
index 53e4a54..a476ef5 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
@@ -57,7 +57,7 @@
 
     private final ComponentResources containerResources;
 
-    private final PageResources pageResources;
+    private final ComponentPageElementResources componentPageElementResources;
 
     // Case insensitive
     private Map<String, Binding> bindings;
@@ -68,14 +68,15 @@
     private Map<String, Object> renderVariables;
 
     public InternalComponentResourcesImpl(Page page, ComponentPageElement element,
-                                          ComponentResources containerResources, PageResources pageResources,
+                                          ComponentResources containerResources,
+                                          ComponentPageElementResources componentPageElementResources,
                                           String completeId, String nestedId, Instantiator componentInstantiator
     )
     {
         this.page = page;
         this.element = element;
         this.containerResources = containerResources;
-        this.pageResources = pageResources;
+        this.componentPageElementResources = componentPageElementResources;
         this.completeId = completeId;
         this.nestedId = nestedId;
 
@@ -119,35 +120,29 @@
         return getFieldChange(fieldName) != null;
     }
 
-    /**
-     * Delegates to the {@link Page#createComponentEventLink(String, String, boolean, Object[])} on the containing page.
-     * Uses the element's nested id (i.e., a mixin can generate a link, but the link targets the component, not the
-     * mixin itself). Why the extra layer? Trying to avoid some unwanted injection (of LinkFactory, into every component
-     * page element).
-     */
-    public Link createActionLink(String eventType, boolean forForm, Object... context)
-    {
-        return page.createComponentEventLink(element.getNestedId(), eventType, forForm, context);
-    }
-
     public Link createEventLink(String eventType, Object... context)
     {
-        return page.createComponentEventLink(element.getNestedId(), eventType, false, context);
+        return element.createEventLink(eventType, context);
+    }
+
+    public Link createActionLink(String eventType, boolean forForm, Object... context)
+    {
+        return element.createActionLink(eventType, forForm, context);
     }
 
     public Link createFormEventLink(String eventType, Object... context)
     {
-        return page.createComponentEventLink(element.getNestedId(), eventType, true, context);
+        return element.createFormEventLink(eventType, context);
     }
 
     public Link createPageLink(String pageName, boolean override, Object... context)
     {
-        return page.createPageRenderLink(pageName, override, context);
+        return element.createPageLink(pageName, override, context);
     }
 
     public Link createPageLink(Class pageClass, boolean override, Object... context)
     {
-        return page.createPageRenderLink(pageClass, override, context);
+        return element.createPageLink(pageClass, override, context);
     }
 
     public void discardPersistentFieldChanges()
@@ -276,7 +271,7 @@
 
             Object boundValue = b.get();
 
-            result = pageResources.coerce(boundValue, expectedType);
+            result = componentPageElementResources.coerce(boundValue, expectedType);
         }
         catch (Exception ex)
         {
@@ -303,7 +298,7 @@
 
     public Object readParameter(String parameterName, String desiredTypeName)
     {
-        Class parameterType = pageResources.toClass(desiredTypeName);
+        Class parameterType = componentPageElementResources.toClass(desiredTypeName);
 
         return readParameter(parameterName, parameterType);
     }
@@ -324,7 +319,7 @@
 
         try
         {
-            Object coerced = pageResources.coerce(parameterValue, bindingType);
+            Object coerced = componentPageElementResources.coerce(parameterValue, bindingType);
 
             b.set(coerced);
         }
@@ -376,7 +371,7 @@
 
             if (value instanceof Block) continue;
 
-            String valueString = pageResources.coerce(value, String.class);
+            String valueString = componentPageElementResources.coerce(value, String.class);
 
             writer.attributes(name, valueString);
         }
@@ -406,7 +401,7 @@
 
     public Messages getMessages()
     {
-        if (messages == null) messages = pageResources.getMessages(componentModel);
+        if (messages == null) messages = componentPageElementResources.getMessages(componentModel);
 
         return messages;
     }
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
index b2baf52..c54011a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
@@ -15,7 +15,6 @@
 package org.apache.tapestry5.internal.structure;
 
 import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.Link;
 import org.apache.tapestry5.runtime.Component;
 import org.apache.tapestry5.runtime.PageLifecycleListener;
 import org.slf4j.Logger;
@@ -113,27 +112,6 @@
     ComponentPageElement getComponentElementByNestedId(String nestedId);
 
     /**
-     * Creates a link that will trigger behavior in a component within the page.
-     *
-     * @see org.apache.tapestry5.ComponentResources#createEventLink(String, Object[])
-     */
-    Link createComponentEventLink(String nestedId, String eventType, boolean forForm, Object... context);
-
-    /**
-     * Creates a link to the named page.
-     *
-     * @see org.apache.tapestry5.ComponentResources#createPageLink(String, boolean, Object[])
-     */
-    Link createPageRenderLink(String pageName, boolean override, Object... context);
-
-    /**
-     * Creates a link to the named page.
-     *
-     * @see org.apache.tapestry5.ComponentResources#createPageLink(Class, boolean, Object[])
-     */
-    Link createPageRenderLink(Class pageClass, boolean override, Object... context);
-
-    /**
      * Posts a change to a persistent field.
      *
      * @param resources the component resources for the component or mixin containing the field whose value changed
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java
index 984e6ba..6f4570a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java
@@ -15,16 +15,12 @@
 package org.apache.tapestry5.internal.structure;
 
 import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.Link;
-import org.apache.tapestry5.internal.services.LinkFactory;
 import org.apache.tapestry5.internal.services.PersistentFieldManager;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import org.apache.tapestry5.ioc.internal.util.Defense;
 import static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.runtime.Component;
 import org.apache.tapestry5.runtime.PageLifecycleListener;
-import org.apache.tapestry5.services.ComponentClassResolver;
 import org.apache.tapestry5.services.PersistentFieldBundle;
 import org.slf4j.Logger;
 
@@ -37,12 +33,8 @@
 
     private final Locale locale;
 
-    private final LinkFactory linkFactory;
-
     private final PersistentFieldManager persistentFieldManager;
 
-    private final ComponentClassResolver componentClassResolver;
-
     private ComponentPageElement rootElement;
 
     private final List<PageLifecycleListener> listeners = CollectionFactory.newList();
@@ -55,14 +47,11 @@
      */
     private PersistentFieldBundle fieldBundle;
 
-    public PageImpl(String logicalPageName, Locale locale, LinkFactory linkFactory,
-                    PersistentFieldManager persistentFieldManager, ComponentClassResolver componentClassResolver)
+    public PageImpl(String logicalPageName, Locale locale, PersistentFieldManager persistentFieldManager)
     {
         this.logicalPageName = logicalPageName;
         this.locale = locale;
-        this.linkFactory = linkFactory;
         this.persistentFieldManager = persistentFieldManager;
-        this.componentClassResolver = componentClassResolver;
     }
 
     @Override
@@ -156,25 +145,6 @@
         return rootElement.getLogger();
     }
 
-    public Link createComponentEventLink(String nestedId, String eventType, boolean forForm, Object... context)
-    {
-        return linkFactory.createComponentEventLink(this, nestedId, eventType, forForm, context);
-    }
-
-    public Link createPageRenderLink(String pageName, boolean override, Object... context)
-    {
-        return linkFactory.createPageLink(pageName, override, context);
-    }
-
-    public Link createPageRenderLink(Class pageClass, boolean override, Object... context)
-    {
-        Defense.notNull(pageClass, "pageClass");
-
-        String pageName = componentClassResolver.resolvePageClassNameToPageName(pageClass.getName());
-
-        return linkFactory.createPageLink(pageName, override, context);
-    }
-
     public void persistFieldChange(ComponentResources resources, String fieldName, Object newValue)
     {
         persistentFieldManager.postChange(logicalPageName, resources, fieldName, newValue);
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventImplTest.java
index 948d045..f0fef1f 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventImplTest.java
@@ -17,7 +17,7 @@
 import org.apache.tapestry5.ComponentEventCallback;
 import org.apache.tapestry5.EventContext;
 import org.apache.tapestry5.TapestryMarkers;
-import org.apache.tapestry5.internal.structure.PageResources;
+import org.apache.tapestry5.internal.structure.ComponentPageElementResources;
 import org.apache.tapestry5.internal.test.InternalBaseTestCase;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.runtime.ComponentEvent;
@@ -120,7 +120,7 @@
     public void coerce_context()
     {
         ComponentEventCallback handler = mockComponentEventHandler();
-        PageResources resources = mockPageResources();
+        ComponentPageElementResources resources = mockComponentPageElementResources();
         EventContext context = mockEventContext();
         Integer value = new Integer(27);
 
@@ -173,7 +173,7 @@
     {
         ComponentEventCallback handler = mockComponentEventHandler();
         EventContext context = mockEventContext();
-        PageResources resources = mockPageResources();
+        ComponentPageElementResources resources = mockComponentPageElementResources();
         Logger logger = mockLogger();
 
         logger.debug(eq(TapestryMarkers.EVENT_HANDLER_METHOD), isA(String.class), isA(String.class));
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkFactoryImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkFactoryImplTest.java
index 1be1cb8..98d7aed 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkFactoryImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkFactoryImplTest.java
@@ -56,7 +56,6 @@
     public void action_link_root_context_no_ids()
     {
         testActionLink("", PAGE_LOGICAL_NAME, "foo.bar", "someaction", "/sub/mypage.foo.bar:someaction");
-
     }
 
     @Test
@@ -321,7 +320,7 @@
                                                   securityManager);
         factory.addListener(listener);
 
-        Link link = factory.createPageLink(PAGE_LOGICAL_NAME, false);
+        Link link = factory.createPageRenderLink(PAGE_LOGICAL_NAME, false);
 
         assertEquals(link.toRedirectURI(), ENCODED);
 
@@ -373,7 +372,7 @@
                                                   securityManager);
         factory.addListener(listener);
 
-        Link link = factory.createPageLink(logicalName, false);
+        Link link = factory.createPageRenderLink(logicalName, false);
 
         assertEquals(link.toRedirectURI(), ENCODED);
 
@@ -425,7 +424,7 @@
                                                   securityManager);
         factory.addListener(listener);
 
-        Link link = factory.createPageLink(logicalName, false);
+        Link link = factory.createPageRenderLink(logicalName, false);
 
         assertEquals(link.toRedirectURI(), ENCODED);
 
@@ -661,5 +660,4 @@
 
         verify();
     }
-
 }
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageLoaderImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageLoaderImplTest.java
index 92cbb9f..ffccd09 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageLoaderImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageLoaderImplTest.java
@@ -80,7 +80,7 @@
 
         replay();
 
-        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, null, null, resolver);
+        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, null, resolver);
 
         Page page = loader.loadPage(LOGICAL_PAGE_NAME, LOCALE);
 
@@ -164,11 +164,10 @@
 
         replay();
 
-        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, null, null, resolver);
+        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, null, resolver);
 
         loader.loadPage(LOGICAL_PAGE_NAME, LOCALE);
 
         verify();
     }
-
 }
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ComponentPageElementImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ComponentPageElementImplTest.java
index fefde30..50cc376 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ComponentPageElementImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ComponentPageElementImplTest.java
@@ -330,7 +330,7 @@
         Component component = mockComponent();
         ComponentModel model = mockComponentModel();
         Binding binding = mockBinding();
-        PageResources resources = mockPageResources();
+        ComponentPageElementResources resources = mockComponentPageElementResources();
         Logger logger = mockLogger();
 
         train_getLogger(model, logger);
@@ -365,7 +365,7 @@
         Page page = newPage(PAGE_NAME);
         Component component = mockComponent();
         ComponentModel model = mockComponentModel();
-        PageResources resources = mockPageResources();
+        ComponentPageElementResources resources = mockComponentPageElementResources();
         Binding binding = mockBinding();
         Logger logger = mockLogger();
 
@@ -566,7 +566,6 @@
         }
 
         verify();
-
     }
 
     @Test
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImplTest.java
index eb089cd..ed582ae 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImplTest.java
@@ -89,7 +89,7 @@
         Binding binding = mockBinding();
         Object rawValue = new Object();
         String convertedValue = "*converted*";
-        PageResources pageResources = mockPageResources();
+        ComponentPageElementResources componentPageElementResources = mockComponentPageElementResources();
 
         train_getModel(ins, model);
 
@@ -97,13 +97,14 @@
 
         train_get(binding, rawValue);
 
-        train_coerce(pageResources, rawValue, String.class, convertedValue);
+        train_coerce(componentPageElementResources, rawValue, String.class, convertedValue);
 
         writer.attributes("fred", convertedValue);
 
         replay();
 
-        InternalComponentResources resources = new InternalComponentResourcesImpl(null, element, null, pageResources,
+        InternalComponentResources resources = new InternalComponentResourcesImpl(null, element, null,
+                                                                                  componentPageElementResources,
                                                                                   null, null, ins);
 
         resources.bindParameter("fred", binding);
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java
index 7512712..84698f8 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@
 
         replay();
 
-        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, null, null);
+        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
 
         assertNull(page.getRootElement());
 
@@ -60,7 +60,7 @@
 
         replay();
 
-        Page page = new PageImpl(null, locale, null, null, null);
+        Page page = new PageImpl(null, locale, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);
@@ -82,7 +82,7 @@
 
         replay();
 
-        Page page = new PageImpl(null, locale, null, null, null);
+        Page page = new PageImpl(null, locale, null);
 
         page.addLifecycleListener(listener);
 
@@ -116,7 +116,7 @@
 
         replay();
 
-        Page page = new PageImpl(null, locale, null, null, null);
+        Page page = new PageImpl(null, locale, null);
         page.setRootElement(element);
 
         page.addLifecycleListener(listener1);
@@ -144,7 +144,7 @@
 
         replay();
 
-        Page page = new PageImpl(null, locale, null, null, null);
+        Page page = new PageImpl(null, locale, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);
@@ -170,7 +170,7 @@
 
         replay();
 
-        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, null, null);
+        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);
@@ -187,7 +187,7 @@
 
         replay();
 
-        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, null, null);
+        Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
 
         page.setRootElement(root);
 
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
index a2b238c..3394197 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
@@ -21,9 +21,9 @@
 import org.apache.tapestry5.internal.parser.TemplateToken;
 import org.apache.tapestry5.internal.services.*;
 import org.apache.tapestry5.internal.structure.ComponentPageElement;
+import org.apache.tapestry5.internal.structure.ComponentPageElementResources;
 import org.apache.tapestry5.internal.structure.Page;
 import org.apache.tapestry5.internal.structure.PageElement;
-import org.apache.tapestry5.internal.structure.PageResources;
 import org.apache.tapestry5.ioc.*;
 import org.apache.tapestry5.ioc.def.ContributionDef;
 import org.apache.tapestry5.ioc.def.ModuleDef;
@@ -580,20 +580,21 @@
         expect(queue.getRenderingPage()).andReturn(page);
     }
 
-    protected final PageResources mockPageResources()
+    protected final ComponentPageElementResources mockComponentPageElementResources()
     {
-        return newMock(PageResources.class);
+        return newMock(ComponentPageElementResources.class);
     }
 
-    protected final void train_toClass(PageResources resources, String className, Class toClass)
+    protected final void train_toClass(ComponentPageElementResources resources, String className, Class toClass)
     {
         expect(resources.toClass(className)).andReturn(toClass).atLeastOnce();
     }
 
-    protected final <S, T> void train_coerce(PageResources pageResources, S input, Class<T> expectedType,
+    protected final <S, T> void train_coerce(ComponentPageElementResources componentPageElementResources, S input,
+                                             Class<T> expectedType,
                                              T coercedValue)
     {
-        expect(pageResources.coerce(input, expectedType)).andReturn(coercedValue);
+        expect(componentPageElementResources.coerce(input, expectedType)).andReturn(coercedValue);
     }
 
     protected final EventContext mockEventContext()