You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2008/11/11 08:44:56 UTC
svn commit: r712972 - in /myfaces/trinidad/trunk_1.2.x:
trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/
trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/ trini...
Author: matzew
Date: Mon Nov 10 23:44:55 2008
New Revision: 712972
URL: http://svn.apache.org/viewvc?rev=712972&view=rev
Log:
TRINIDAD-1243 - Adding a change implementation to the ChangeManager framework
Thx to Prakash Udupa N for his patch
Added:
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/MoveChildComponentChange.java
Removed:
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeMarker.java
Modified:
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/AddChildComponentChange.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/BaseChangeManager.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeManager.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeUtils.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/SessionChangeManager.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentELTag.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentTag.java
myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/change/NullChangeManager.java
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/AddChildComponentChange.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/AddChildComponentChange.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/AddChildComponentChange.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/AddChildComponentChange.java Mon Nov 10 23:44:55 2008
@@ -24,6 +24,7 @@
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
/**
* Change specialization for adding a child component.
* While applying this Change, the child component is re-created and added to
@@ -89,10 +90,13 @@
// to-be-added child, remove it and get the new one added.
UIComponent removableChild = ChangeUtils.getChildForId(uiComponent, newChildId);
+ // Users can add component themselves in addition to adding a ComponentChange
+ // This could cause duplicates, which is fine. Handle this gracefully with
+ // a info log and replacement
if (removableChild != null)
{
- throw new IllegalStateException(_LOG.getMessage(
- "ATTEMP_ADD_DUPLICATE_ID", newChildId));
+ _LOG.info("ATTEMPT_ADD_CHILD_WITH_DUPLICATE_ID", newChildId);
+ children.remove(removableChild);
}
if (_insertBeforeId == null)
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/BaseChangeManager.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/BaseChangeManager.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/BaseChangeManager.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/BaseChangeManager.java Mon Nov 10 23:44:55 2008
@@ -18,23 +18,18 @@
*/
package org.apache.myfaces.trinidad.change;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
-import org.w3c.dom.Document;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.w3c.dom.Document;
+
/**
* Base ChangeManager implementation that manages the bookkeeping for
* supporting both ComponentChanges and DocumentChanges.
- * subclasses must implement getComponentToChangesMapForView to implement
+ * subclasses must implement addComponentChangeImpl() to implement
* the ComponentChange support. To support DocumentChanges,
* <code>getDocument</code> must be implemented.
*
@@ -45,7 +40,6 @@
/**
* {@inheritDoc}
*/
- // TODO : Maybe we need to allow adding Changes for specific viewId's
@Override
public void addComponentChange(
FacesContext facesContext,
@@ -57,7 +51,7 @@
"CANNOT_ADD_CHANGE_WITH_FACECONTEXT_OR_UICOMPONENT_OR_NULL"));
// add the change to the component
- _addComponentChangeImpl(facesContext, uiComponent, change);
+ addComponentChangeImpl(facesContext, uiComponent, change);
if (supportsDocumentPersistence(facesContext))
{
@@ -81,89 +75,19 @@
}
/**
- * {@inheritDoc}
+ * A no-op implementation of adding a ComponentChange. Sub-classers should
+ * override and provide an implementation if they support component changes.
+ * @param facesContext The FacesContext for this request.
+ * @param targetComponent The target component against which this change needs
+ * to be registered and applied later on.
+ * @param componentChange The ComponentChange to add
*/
- @Override
- public Iterator<ComponentChange> getComponentChanges(
+ protected void addComponentChangeImpl(
FacesContext facesContext,
- UIComponent uiComponent)
- {
- if (uiComponent == null)
- return null;
-
- String viewId = facesContext.getViewRoot().getViewId();
- Map<String, List<ComponentChange>> componentToChangesMap =
- getComponentToChangesMapForView(facesContext, viewId, false);
-
- if (componentToChangesMap == null)
- return null;
-
- String uniqueIdForComponent = _getUniqueIdForComponent(uiComponent);
- List<ComponentChange> changesList = componentToChangesMap.get(uniqueIdForComponent);
- if (changesList == null)
- return null;
-
- return changesList.iterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator<String> getComponentIdsWithChanges(FacesContext facesContext)
+ UIComponent targetComponent,
+ ComponentChange componentChange)
{
- String viewId = facesContext.getViewRoot().getViewId();
- Map<String, List<ComponentChange>> componentToChangesMap =
- getComponentToChangesMapForView(facesContext, viewId, false);
-
- if (componentToChangesMap == null)
- return null;
-
- return componentToChangesMap.keySet().iterator();
- }
-
- /**
- * The Map used to store the Changes. The Map is stored as
- * key=ComponentCompositeId, value=ChangesList (List)
- *
- * @param facesContext FacesContext for request
- * @param viewId viewID for request
- * @param createIfNecessary <code>true</code> if Map should be created if not
- * already present
- * @return Map of componentID tokens to Lists of Changes
- */
- protected abstract Map<String, List<ComponentChange>> getComponentToChangesMapForView(
- FacesContext facesContext,
- String viewId,
- boolean createIfNecessary);
-
- /**
- * Implementation of adding a ComponentChange
- * @param change ComponentChange to add
- */
- private void _addComponentChangeImpl(
- FacesContext facesContext,
- UIComponent uiComponent,
- ComponentChange change)
- {
- String viewId = facesContext.getViewRoot().getViewId();
-
- Map<String, List<ComponentChange>> componentToChangesMap = getComponentToChangesMapForView(facesContext,
- viewId,
- true);
-
- String uniqueIdForComponent = _getUniqueIdForComponent(uiComponent);
-
- List<ComponentChange> changeListForComponent =
- componentToChangesMap.get(uniqueIdForComponent);
-
- if (changeListForComponent == null)
- {
- changeListForComponent = new CopyOnWriteArrayList<ComponentChange>();
- componentToChangesMap.put(uniqueIdForComponent, changeListForComponent);
- }
-
- changeListForComponent.add(change);
+ //no-op
}
// =-= bts Testing hack hook
@@ -173,26 +97,6 @@
// noop
}
- static private String _getUniqueIdForComponent(UIComponent uiComponent)
- {
- //pu: If this component were to be a NamingContainer, we treat itself as its
- // own closest ancestor that is a NamingContainer. Matches algorithm of
- // UIComponent.findComponent().
- UIComponent ancestor = uiComponent;
- StringBuffer uniqueIdBuffer = new StringBuffer();
- uniqueIdBuffer.append(uiComponent.getId());
- while (ancestor != null)
- {
- if (ancestor instanceof NamingContainer)
- {
- uniqueIdBuffer.insert(0,new StringBuffer().append(ancestor.getId()).
- append(NamingContainer.SEPARATOR_CHAR));
- }
- ancestor = ancestor.getParent();
- }
- return uniqueIdBuffer.toString();
- }
-
/**
* Override to return the Document to modify as part of document-based
* persistence.
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeManager.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeManager.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeManager.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeManager.java Mon Nov 10 23:44:55 2008
@@ -19,13 +19,16 @@
package org.apache.myfaces.trinidad.change;
import java.util.HashMap;
-import java.util.Iterator;
+
+import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
/**
* The base class for all ChangeManagers.
* A ChangeManager should manage accumulation of Changes and also
@@ -132,8 +135,6 @@
return null;
}
-
-
/**
* Add a ComponentChange to this current request for a specified component.
* @throws IllegalArgumentException if any of the supplied parameters were to
@@ -160,26 +161,16 @@
}
/**
- * Retrieve the ComponentChanges available for specified component on this
- * request.
- * @return An Iterator of ComponentChanges in the order in which they
- * are associated with the UIComponent.
- * Returns <code>null<code> if there are no such Changes
+ * Applies all the ComponentChanges added so far for the current view.
+ * Developers should not need to call this method. Internal implementation
+ * will call it as the component tree is built and is ready to take changes.
+ * @param facesContext The FacesContext instance for the current request.
*/
- public abstract Iterator<ComponentChange> getComponentChanges(
- FacesContext facesContext,
- UIComponent uiComponent);
-
- /**
- * Retrieve the identifiers of all components on this request that have Changes
- * associated with them for the viewId specified in the facesContext.
- * @param facesContext
- * @return An Iterator that can be used to access the collection of component
- * identifiers. Returns null if there are no such components.
- */
- public abstract Iterator<String> getComponentIdsWithChanges(
- FacesContext facesContext);
-
+ public void applyComponentChangesForCurrentView(FacesContext facesContext)
+ {
+ throw new UnsupportedOperationException("Subclassers must implement");
+ }
+
private static class AttributeConverter extends DocumentChangeFactory
{
@Override
@@ -192,18 +183,26 @@
Object value = change.getAttributeValue();
// =-= bts TODO add registration of attribute converters
+ String valueString = null;
if ((value == null) ||
(value instanceof CharSequence) ||
(value instanceof Number) ||
(value instanceof Boolean))
{
- String valueString = (value != null)
- ? value.toString()
- : null;
-
+ valueString = (value != null)? value.toString() : null;
+ }
+ else if (value instanceof ValueExpression)
+ {
+ valueString = ((ValueExpression)value).getExpressionString();
+ }
+ else if (value instanceof ValueBinding)
+ {
+ valueString = ((ValueBinding)value).getExpressionString();
+ }
+
+ if (valueString != null)
return new AttributeDocumentChange(change.getAttributeName(),
valueString);
- }
}
// no conversion possible
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeUtils.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeUtils.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/ChangeUtils.java Mon Nov 10 23:44:55 2008
@@ -20,19 +20,21 @@
import java.util.List;
+import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
-import org.apache.myfaces.trinidad.logging.TrinidadLogger;
/**
* Utility functions for use by Changes.
* @version $Name: $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/change/ChangeUtils.java#0 $) $Date: 10-nov-2005.19:09:58 $
*/
-class ChangeUtils
+final class ChangeUtils
{
private ChangeUtils()
{
@@ -119,6 +121,50 @@
}
/**
+ * Search the supplied Node and its descendants for an Element Node with the
+ * scopedTargetId.
+ * @param baseNode The base Node of the subtree relative to which the target
+ * Node is to be found.
+ * @param scopedTargetId The scoped id of the target node which is to be found.
+ * This id should be relative from the base Node of the search, with
+ * NamingContainer.SEPARATOR_CHAR being the separator for fragments. If the
+ * targetId starts with a NamingContainer.SEPARATOR_CHAR, it is considered
+ * as an absolute id, and the owner Document will be the base Node of search.
+ * Examples of scopedTargetId values: 'foo:bar:baz'/':foo:bar:baz'/'foo'.
+ * @param searchDepth The integer which indicates till how many levels deeper
+ * from the baseNode, the search has to be performed.
+ * @return The target Node with the given scopedTargetId if found within the
+ * permitted searchDepth, else null
+ */
+ static Node __findNodeByScopedId(
+ Node baseNode,
+ String scopedTargetId,
+ int searchDepth)
+ {
+ if (baseNode == null ||
+ scopedTargetId == null ||
+ scopedTargetId.length() == 0)
+ return null;
+
+ // Check if we have received an absolute id.
+ if (NamingContainer.SEPARATOR_CHAR == scopedTargetId.charAt(0))
+ {
+ // If so directly deal with the owner Document.
+ if (baseNode.getNodeType() != Node.DOCUMENT_NODE)
+ baseNode = baseNode.getOwnerDocument();
+
+ // Remove leading ':'
+ scopedTargetId = scopedTargetId.substring(1);
+ }
+
+ // 'foo:bar:baz' -> ['foo'],['bar'},['baz']
+ String[] idFrags =
+ scopedTargetId.split(String.valueOf(NamingContainer.SEPARATOR_CHAR));
+
+ return _traceNodeByIdPath(baseNode, idFrags, 0, searchDepth);
+ }
+
+ /**
* Given a node representing a component, returns the named facet's Element.
* @param componentNode The node to search for a facet contained in it.
* @param facetName The name of the facet to search for.
@@ -171,7 +217,67 @@
}
}
+ /**
+ * Traces for the targetNode recursively in the subtree rooted by baseNode.
+ * Trace path is also controlled by the id path fragments and the fragIndex.
+ * Trace stops when the permitted searchDepth is reached, or when the trace
+ * faled.
+ * @returns The traget node of the search. Returns null if the target Node is
+ * not to be found, or if we have exceeded the search depth.
+ */
+ private static Node _traceNodeByIdPath(
+ Node baseNode,
+ String[] idFrags,
+ int fragIndex,
+ int searchDepth)
+ {
+ if ((baseNode.getNodeType() == Node.ELEMENT_NODE) &&
+ idFrags[fragIndex].equals(((Element)baseNode).getAttribute(_ID_ATTRIB_NAME)))
+ {
+ if (idFrags.length == fragIndex + 1)
+ {
+ // This is the node for the last of the id fragments, so we found the
+ // target now.
+ return baseNode;
+ }
+ else
+ {
+ // This is the intermediate node matching the path, start looking for
+ // nodes with id's matching rest of fragments.
+ fragIndex++;
+ }
+ }
+
+ // Check child Nodes
+ if (searchDepth > 0)
+ {
+ searchDepth--;
+
+ Node currChild = baseNode.getFirstChild();
+
+ while (currChild != null)
+ {
+ if (Node.ELEMENT_NODE == currChild.getNodeType())
+ {
+ Node targetNode = _traceNodeByIdPath(currChild,
+ idFrags,
+ fragIndex,
+ searchDepth);
+ if (targetNode != null)
+ return targetNode;
+ }
+
+ currChild = currChild.getNextSibling();
+ }
+ }
+
+ // We are past the permitted search depth, or we searched the entire subtree
+ // in vain, abort.
+ return null;
+ }
+
static final String __JSF_CORE_NAMESPACE = "http://java.sun.com/jsf/core";
+ private static final String _ID_ATTRIB_NAME = "id";
private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
ChangeUtils.class);
}
Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/MoveChildComponentChange.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/MoveChildComponentChange.java?rev=712972&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/MoveChildComponentChange.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/MoveChildComponentChange.java Mon Nov 10 23:44:55 2008
@@ -0,0 +1,435 @@
+package org.apache.myfaces.trinidad.change;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.trinidad.component.UIXComponent;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.ComponentUtils;
+
+import org.w3c.dom.Node;
+
+
+/**
+ * Change specialization for moving a child from one container to another.
+ * MoveChildComponent should be registered on a parent component that is
+ * common to the child being moved and the container component at destination.
+ * In other words, while calling addComponentChange() or addDocumentChange()
+ * methods on the ChangeManager to add a MoveChildComponentChange, the common
+ * parent component instance must be passed as an argument. The add() utility
+ * method in this class can be alternatively used to conveniently register the
+ * change against the common parent. While applying this change, if a child with
+ * the same identifier as the movable child were to be already present in the
+ * destination container, it will be considered as a duplicate child, will be
+ * removed and movable child will be added.
+ * @see #add(FacesContext, ChangeManager)
+ * @see ChangeManager#addComponentChange(FacesContext, UIComponent, ComponentChange)
+ * @see ChangeManager#addDocumentChange(FacesContext, UIComponent, DocumentChange)
+ */
+public final class MoveChildComponentChange
+ extends ComponentChange
+ implements DocumentChange
+{
+ /**
+ * Constructs a MoveChildComponentChange. The child will be appended to the
+ * list of children of the destinationContainer.
+ * @param movableChild The child component to be moved.
+ * @param destinationContainer The destination component into which the child
+ * component is to be moved.
+ * @throws IllegalArgumentException If movableChild or destinationContainer
+ * is null
+ */
+ public MoveChildComponentChange(
+ UIComponent movableChild,
+ UIComponent destinationContainer)
+ {
+ this(movableChild, destinationContainer, null);
+ }
+
+ /**
+ * Constructs a MoveChildComponentChange. The child will be inserted to the
+ * list of children of the destinationContainer, before the supplied
+ * insertBeforecomponent. If the supplied insertBeforeComponent is null, the
+ * child will be appended to the list of children of the destinationContainer.
+ * If the insertBeforeComponent is non-null, and if it were not to be found
+ * while applying this change, the movableChild will not be moved.
+ * @param movableChild The child component to be moved.
+ * @param destinationContainer The destination component into which the child
+ * component is to be moved.
+ * @param insertBeforeComponent The component before which the moved child is
+ * to be inserted. This can be null, in which case the movableChild is
+ * appended.
+ * @throws IllegalArgumentException If movableChild or destinationContainer
+ * is null, or if a parent component common to movableChild and
+ * destinationContainer could not be found.
+ */
+ public MoveChildComponentChange(
+ UIComponent movableChild,
+ UIComponent destinationContainer,
+ UIComponent insertBeforeComponent)
+ {
+ if (movableChild == null)
+ throw new IllegalArgumentException(
+ _LOG.getMessage("MOVABLE_CHILD_REQUIRED"));
+
+ if (destinationContainer == null)
+ throw new IllegalArgumentException(
+ _LOG.getMessage("DESTINATION_CONTAINER_REQUIRED"));
+
+ // Get the common parent
+ _commonParent =
+ _getClosestCommonParentUIXComponent(movableChild, destinationContainer);
+
+ if (_commonParent == null)
+ throw new IllegalArgumentException(
+ _LOG.getMessage("COMMON_PARENT_NOT_FOUND"));
+
+ // Get the scoped id's for all participants
+ _movableChildScopedId =
+ ComponentUtils.getScopedIdForComponent(movableChild, _commonParent);
+ _sourceParentScopedId =
+ ComponentUtils.getScopedIdForComponent(movableChild.getParent(),
+ _commonParent);
+ _destinationContainerScopedId =
+ ComponentUtils.getScopedIdForComponent(destinationContainer, _commonParent);
+ _commonParentScopedId =
+ ComponentUtils.getScopedIdForComponent(_commonParent, null);
+
+ if (_movableChildScopedId == null ||
+ _sourceParentScopedId == null ||
+ _destinationContainerScopedId == null ||
+ _commonParentScopedId == null)
+ throw new IllegalArgumentException(
+ _LOG.getMessage("MOVE_PARTICIPANTS_WITHOUT_ID"));
+
+ // For insertBeforeComponent, we do not care to obtain scoped id.
+ _insertBeforeId = (insertBeforeComponent == null) ?
+ null:insertBeforeComponent.getId();
+ }
+
+ /**
+ * Convenience method to add this MoveChildComponentChange to the supplied
+ * ChangeManager. The change will be registered against a parent component
+ * that is common to the child being moved and the container component at
+ * destination.
+ * @param facesContext The FacesContext instance for the current request
+ * @param changeManager The ChangeManager instance on which this
+ * MoveChildComponentChange is to be added.
+ * @return The common parent component against which this
+ * MoveChildComponentChange was registered.
+ */
+ public UIComponent add(
+ FacesContext facesContext,
+ ChangeManager changeManager)
+ {
+ UIComponent commonParent = _commonParent;
+
+ if (commonParent == null)
+ commonParent =
+ facesContext.getViewRoot().findComponent(_commonParentScopedId);
+ if (commonParent == null)
+ {
+ _LOG.warning("COMMON_PARENT_NOT_FOUND", _commonParentScopedId);
+ return null;
+ }
+
+ // Register a move change against the common parent
+ changeManager.addComponentChange(facesContext, commonParent, this);
+
+ // We dont need to keep the common parent anymore
+ _commonParent = null;
+
+ return commonParent;
+ }
+
+ /**
+ * Apply this change to the specified component.
+ * @param changeTargetComponent The component that is a common parent to the
+ * movable child and the destination container.
+ * @throws IllegalArgumentException If the supplied changeTargetComponent
+ * is null.
+ */
+ @Override
+ public void changeComponent(UIComponent changeTargetComponent)
+ {
+ if (changeTargetComponent == null)
+ throw new IllegalArgumentException(
+ _LOG.getMessage("COMPONENT_REQUIRED"));
+
+ // 1. Check for destination container component
+ UIComponent destinationContainer =
+ changeTargetComponent.findComponent(_destinationContainerScopedId);
+ if(destinationContainer == null)
+ {
+ _LOG.warning("DESTINATION_CONTAINER_NOT_FOUND",
+ _destinationContainerScopedId);
+ return;
+ }
+
+ // 2. Find movableChild, gather any duplicates and remove them.
+ // Duplicates are possible because
+ // a) taghandlers re-create the component that was in the jspx file in
+ // their original location, no matter whether it was moved/removed due to
+ // aplication of a different ComponentChange. Such components could now
+ // be considered duplicates. In theory, there could be just one such
+ // duplicate.
+ // b) We would have moved/added components due to an earlier application of
+ // a ComponentChange, that could still be in the view tree. Such
+ // components must now be considered duplicates. In theory, there could
+ // be just one such duplicate.
+ // This issue of duplicates is more common when the movement is within same
+ // NamingContainer.
+ UIComponent sourceParent =
+ changeTargetComponent.findComponent(_sourceParentScopedId);
+
+ UIComponent foundChild =
+ changeTargetComponent.findComponent(_movableChildScopedId);
+ //Assume the first found child is the movableChild
+ UIComponent movableChild = foundChild;
+ int movableChildIndex = 0;
+ while (foundChild != null)
+ {
+ // If the parent matches, this is the one to move, rest are duplicates
+ if (foundChild.getParent().equals(sourceParent))
+ {
+ movableChild = foundChild;
+ movableChildIndex = sourceParent.getChildren().indexOf(movableChild);
+ }
+
+ // Invariably, remove the found component from the tree. We remove the
+ // movableChild also, otherwise, findComponent blind loops on this same
+ // component if movableChild and duplicates are within same immediate
+ // NamingContainer.
+ foundChild.getParent().getChildren().remove(foundChild);
+
+ // Try and find the next potential duplicate
+ foundChild = changeTargetComponent.findComponent(_movableChildScopedId);
+ }
+
+ if(movableChild == null)
+ {
+ _LOG.warning("MOVABLE_CHILD_NOT_FOUND", _movableChildScopedId);
+ return;
+ }
+
+ // Reattach the moveable child, so that move happens atomically at the end.
+ sourceParent.getChildren().add(movableChildIndex, movableChild);
+
+ // 3. If there is a child already existing with the same identifier in the
+ // destination container, remove it. We are doing this before identifying
+ // the insert index so that insert index is accurate, in case we end up
+ // removing any child in this step.
+ String movableChildId = movableChild.getId();
+ int indexOfChildWithSameIdAtDestination = 0;
+ UIComponent childWithSameIdAtDestination = null;
+ for (UIComponent childComponent:destinationContainer.getChildren())
+ {
+ if (movableChildId.equals(childComponent.getId()))
+ {
+ indexOfChildWithSameIdAtDestination =
+ destinationContainer.getChildren().indexOf(childComponent);
+ childWithSameIdAtDestination = childComponent;
+ destinationContainer.getChildren().remove(childComponent);
+ }
+ }
+
+ // 4. See if we can find the insertBeforeComponent among the
+ // destinationContainer's children
+ int insertIndex = -1;
+ if (_insertBeforeId != null)
+ {
+ for (UIComponent childComponent:destinationContainer.getChildren())
+ {
+ if (_insertBeforeId.equals(childComponent.getId()))
+ {
+ insertIndex =
+ destinationContainer.getChildren().indexOf(childComponent);
+ break;
+ }
+ }
+
+ // insertBeforeId was specified, but corresponding component is missing.
+ // In this case abort the move, after re-adding any components in
+ // destination container that we may have deleted from step #3.
+ if (insertIndex == -1)
+ {
+ if (childWithSameIdAtDestination != null)
+ destinationContainer.getChildren().add(
+ indexOfChildWithSameIdAtDestination,
+ childWithSameIdAtDestination);
+
+ _LOG.warning("INSERT_BEFORE_NOT_FOUND", _insertBeforeId);
+ return;
+ }
+ }
+
+ // 5. Atomically move the child
+ if (insertIndex == -1)
+ destinationContainer.getChildren().add(movableChild);
+ else
+ destinationContainer.getChildren().add(insertIndex, movableChild);
+ }
+
+ /**
+ * Given the DOM Node representing a Component, apply any necessary
+ * DOM changes. The node passed will be the Node that is a common parent for
+ * the movable child and the destination container.
+ * There is a limitation with the document change, that the movable child
+ * Node, destination container Node, and the common parent Node have to belong
+ * to the same document.
+ * @param changeTargetNode DOM Node that is a common parent for the movable
+ * child and the destination container.
+ * @throws IllegalArgumentException If changeTargeNode were to be null.
+ */
+ public void changeDocument(Node changeTargetNode)
+ {
+ if (changeTargetNode == null)
+ throw new IllegalArgumentException(_LOG.getMessage("NO_NODE_SPECIFIED"));
+
+ // Move involves four steps.
+ // 1. Finding the child node, the source of move
+ Node movableChildNode =
+ ChangeUtils.__findNodeByScopedId(changeTargetNode,
+ _movableChildScopedId,
+ Integer.MAX_VALUE);
+
+ if(movableChildNode == null)
+ {
+ _LOG.warning("MOVABLE_CHILD_NOT_FOUND", _movableChildScopedId);
+ return;
+ }
+
+ // 2. Finding the destination container node
+ Node destinationContainerNode =
+ ChangeUtils.__findNodeByScopedId(changeTargetNode,
+ _destinationContainerScopedId,
+ Integer.MAX_VALUE);
+
+
+ if(destinationContainerNode == null)
+ {
+ _LOG.warning("DESTINATION_CONTAINER_NOT_FOUND",
+ _destinationContainerScopedId);
+ return;
+ }
+
+ //3. Finding the neighbor at the destination
+ Node insertBeforeNode = (_insertBeforeId == null) ?
+ null:ChangeUtils.__findNodeByScopedId(destinationContainerNode,
+ _insertBeforeId,
+ 1);
+ // insertBeforeId was specified, but corresponding component is missing.
+ // Abort the move.
+ if(_insertBeforeId != null && insertBeforeNode == null)
+ {
+ _LOG.warning("INSERT_BEFORE_NOT_FOUND", _insertBeforeId);
+ return;
+ }
+
+ //4. Atomically move the child.
+ destinationContainerNode.insertBefore(movableChildNode, insertBeforeNode);
+ }
+
+ /**
+ * Returns true if adding the DocumentChange should force the JSP Document
+ * to reload
+ * @return true Since moving of components should force the document to reload
+ */
+ public boolean getForcesDocumentReload()
+ {
+ return true;
+ }
+
+ /**
+ * Returns the first UIXComponent common parent of two components in a
+ * subtree.
+ * @param firstComponent The first UIComponent instance
+ * @param secondComponent The second UIComponent instance
+ * @return UIComponent The closest common parent of the two supplied
+ * components.
+ */
+ private static UIComponent _getClosestCommonParentUIXComponent(
+ UIComponent firstComponent,
+ UIComponent secondComponent)
+ {
+ if (firstComponent == null || secondComponent == null)
+ return null;
+
+ // Calculate the depth of each node.
+ int firstDepth = _computeDepth(firstComponent);
+ int secondDepth = _computeDepth(secondComponent);
+
+ // Move the deeper of the two components to its ancestor at the same depth
+ // as the shallower.
+ if (secondDepth > firstDepth)
+ {
+ secondComponent = _getAncestor(secondComponent, secondDepth - firstDepth);
+ }
+ else if(secondDepth < firstDepth)
+ {
+ firstComponent = _getAncestor(firstComponent, firstDepth - secondDepth);
+ }
+
+ // Crawl up until we find the shared ancestor.
+ while (firstComponent != null && (firstComponent != secondComponent))
+ {
+ firstComponent = firstComponent.getParent();
+ secondComponent = secondComponent.getParent();
+ }
+
+ // Crawl up to first UIXComponent shared parent, since only UIXComponents
+ // have tags that apply changes.
+ UIComponent sharedRoot = firstComponent;
+
+ while ((sharedRoot != null) && !(sharedRoot instanceof UIXComponent))
+ sharedRoot = sharedRoot.getParent();
+
+ return sharedRoot;
+ }
+
+ /**
+ * Returns the depth of a UIComponent in the tree.
+ * @param comp the UIComponent whose depth has to be calculated
+ * @return the depth of the passed in UIComponent
+ */
+ private static int _computeDepth(UIComponent comp)
+ {
+ int i = 0;
+ while((comp = comp.getParent()) != null)
+ {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * Returns the nth ancestor of the passed in component.
+ * @param component The UIComponent whose nth ancestor has to be found
+ * @param level Indicates how many levels to go up from the component
+ * @return The nth ancestor of the component
+ */
+ private static UIComponent _getAncestor(UIComponent component, int level)
+ {
+ assert(level >= 0);
+
+ while(level > 0)
+ {
+ component = component.getParent();
+ level--;
+ }
+ return component;
+ }
+
+ private transient UIComponent _commonParent;
+
+ private final String _movableChildScopedId;
+ private final String _sourceParentScopedId;
+ private final String _destinationContainerScopedId;
+ private final String _commonParentScopedId;
+ private final String _insertBeforeId;
+
+ private static final long serialVersionUID = 1L;
+
+ private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
+ MoveChildComponentChange.class);
+}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/SessionChangeManager.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/SessionChangeManager.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/SessionChangeManager.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/change/SessionChangeManager.java Mon Nov 10 23:44:55 2008
@@ -18,14 +18,24 @@
*/
package org.apache.myfaces.trinidad.change;
+import java.io.Serializable;
+
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.ComponentUtils;
+
import org.w3c.dom.Document;
+
/**
* A ChangeManager implementation that manages
* persisting the added Changes at the session. This means
@@ -35,48 +45,66 @@
public class SessionChangeManager extends BaseChangeManager
{
/**
- * The Map used to store the Changes. The Map is stored as
- * key=ComponentCompositeId, value=ChangesList (List)
- *
- * @param facesContext FacesContext for request
- * @param viewId viewID for request
- * @param createIfNecessary <code>true</code> if Map should be created if not
- * already present
- * @return Synchronized Map of componentID tokens to Lists of Changes
+ * {@inheritDoc}
+ * @param facesContext The FacesContext instance for the current request.
*/
- @SuppressWarnings("unchecked")
@Override
- protected Map<String, List<ComponentChange>> getComponentToChangesMapForView(
- FacesContext facesContext,
- String viewId,
- boolean createIfNecessary)
+ public void applyComponentChangesForCurrentView(FacesContext facesContext)
{
- Map<String, Object> sessMap = facesContext.getExternalContext().getSessionMap();
- //pu: Get datastructure #1 described at the end of this file.
- Map<String, Map<String, List<ComponentChange>>> viewToChangesMap =
- (Map<String, Map<String, List<ComponentChange>>>)sessMap.get(_CHANGE_KEY);
- if (viewToChangesMap == null)
- {
- if (!createIfNecessary)
- return null;
- viewToChangesMap = new ConcurrentHashMap<String, Map<String, List<ComponentChange>>>();
- sessMap.put(_CHANGE_KEY, viewToChangesMap);
- }
+ UIViewRoot viewRoot = facesContext.getViewRoot();
+
+ List<QualifiedComponentChange> componentChangesForView =
+ _getComponentChangesForView(facesContext, viewRoot.getViewId(), false);
- //pu: Get datastructure #2 described at the end of this file.
- Map<String, List<ComponentChange>> componentToChangesMap = viewToChangesMap.get(viewId);
- if (componentToChangesMap == null)
+ for (QualifiedComponentChange qualifiedChange : componentChangesForView)
{
- if (!createIfNecessary)
- return null;
- componentToChangesMap = new ConcurrentHashMap<String, List<ComponentChange>>();
- viewToChangesMap.put(viewId, componentToChangesMap);
+ UIComponent targetComponent =
+ viewRoot.findComponent(qualifiedChange.getTargetComponentScopedId());
+ // Possible that the target component no more exists in the view
+ if (targetComponent != null)
+ {
+ ComponentChange componentChange = qualifiedChange.getComponentChange();
+ componentChange.changeComponent(targetComponent);
+ }
+ else
+ {
+ _LOG.info(this.getClass().getName(),
+ "applyComponentChangesForCurrentView",
+ "TARGET_COMPONENT_MISSING_CHANGE_FAILED",
+ qualifiedChange.getTargetComponentScopedId());
+ }
}
- return componentToChangesMap;
+ }
+
+ /**
+ * Adds a ComponentChange and registers against the supplied component.
+ * Changes added thus live at Session scope.
+ * Use applyComponentChangesForCurrentView() to apply these changes.
+ * @param facesContext The FacesContext instance for the current request.
+ * @param targetComponent The target component against which this change needs
+ * to be registered and applied later on.
+ * @param componentChange The ComponentChange to add.
+ */
+ protected void addComponentChangeImpl(
+ FacesContext facesContext,
+ UIComponent targetComponent,
+ ComponentChange componentChange)
+ {
+ String viewId = facesContext.getViewRoot().getViewId();
+
+ List<QualifiedComponentChange> componentChangesForView =
+ _getComponentChangesForView(facesContext, viewId, true);
+
+ String scopedIdForTargetComponent =
+ ComponentUtils.getScopedIdForComponent(targetComponent, null);
+
+ componentChangesForView.add(
+ new QualifiedComponentChange(scopedIdForTargetComponent,
+ componentChange));
}
/**
- * We don't support DocumentAspect persistence
+ * We don't support DocumentChange persistence
*/
@Override
protected Document getDocument(FacesContext context)
@@ -84,14 +112,96 @@
return null;
}
+ /**
+ * Gets the in-order list of component changes for the given view.
+ * @param facesContext The FacesContext instance for this request.
+ * @param viewId The id of the view for which changes are required.
+ * @param createIfNecessary Indicates whether the underlying datastructures
+ * that store the component changes needs to be created if absent.
+ * @return The in-order list of component changes for the supplied view. This
+ * will be in the same order in which the component changes were added through
+ * calls to <code>addComponentChange()</code>.
+ */
+ private List<QualifiedComponentChange> _getComponentChangesForView(
+ FacesContext facesContext,
+ String viewId,
+ boolean createIfNecessary)
+ {
+ Object session = facesContext.getExternalContext().getSession(true);
+
+ // Key is view id and value is list of component changes for that view
+ ConcurrentHashMap<String, List<QualifiedComponentChange>>
+ componentChangesMapForSession;
+
+ synchronized(session)
+ {
+ Map<String, Object> sessMap =
+ facesContext.getExternalContext().getSessionMap();
+
+ componentChangesMapForSession =
+ (ConcurrentHashMap<String, List<QualifiedComponentChange>>)
+ (sessMap.get(_COMPONENT_CHANGES_MAP_FOR_SESSION_KEY));
+
+ if (componentChangesMapForSession == null)
+ {
+ if (!createIfNecessary)
+ return Collections.emptyList();
+
+ componentChangesMapForSession =
+ new ConcurrentHashMap<String, List<QualifiedComponentChange>>();
+ sessMap.put(_COMPONENT_CHANGES_MAP_FOR_SESSION_KEY,
+ componentChangesMapForSession);
+ }
+ }
+
+ if (!componentChangesMapForSession.containsKey(viewId))
+ {
+ if (!createIfNecessary)
+ return Collections.emptyList();
+
+ // Writes are per change addition, not very frequent, using
+ // CopyOnWriteArrayList should suffice.
+ componentChangesMapForSession.putIfAbsent(
+ viewId,
+ new CopyOnWriteArrayList<QualifiedComponentChange>());
+ }
+
+ return componentChangesMapForSession.get(viewId);
+ }
- static private final String _CHANGE_KEY =
- "org.apache.myfaces.trinidadinternal.Change";
+ private static final class QualifiedComponentChange implements Serializable
+ {
+ public QualifiedComponentChange(String targetComponentScopedId,
+ ComponentChange componentChange)
+ {
+ // NO-TRANS : Class is private and inner, no translated message required
+ if (targetComponentScopedId == null || componentChange == null)
+ throw new IllegalArgumentException("Target component scoped id and " +
+ "component change is required");
+
+ _targetComponentScopedId = targetComponentScopedId;
+ _componentChange = componentChange;
+ }
+
+ public String getTargetComponentScopedId()
+ {
+ return _targetComponentScopedId;
+ }
+
+ public ComponentChange getComponentChange()
+ {
+ return _componentChange;
+ }
+
+ private final String _targetComponentScopedId;
+ private final ComponentChange _componentChange;
+
+ private static final long serialVersionUID = 1L;
+ }
+
+ private static final String _COMPONENT_CHANGES_MAP_FOR_SESSION_KEY =
+ "org.apache.myfaces.trinidadinternal.ComponentChangesMapForSession";
- //pu: DataStructure:
- // 1. Session holds a Map instance named by _CHANGE_KEY
- // [ key=viewId(String), value=ComponenChangesMap(Map) ]
- // 2. ComponenChangesMap is a Map
- // [ key=ComponentCompositeId, value=ChangesList (List) ]
- // 3. ChangesList is a List of Changes for the given component.
+ private static final TrinidadLogger _LOG =
+ TrinidadLogger.createTrinidadLogger(SessionChangeManager.class);
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentELTag.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentELTag.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentELTag.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentELTag.java Mon Nov 10 23:44:55 2008
@@ -25,32 +25,27 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.TimeZone;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
-import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
-import javax.faces.webapp.UIComponentClassicTagBase;
import javax.faces.webapp.UIComponentELTag;
import javax.servlet.jsp.JspException;
-import javax.servlet.jsp.tagext.Tag;
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
-import org.apache.myfaces.trinidad.change.AddComponentChange;
-import org.apache.myfaces.trinidad.change.ChangeMarker;
-import org.apache.myfaces.trinidad.change.ComponentChange;
+import org.apache.myfaces.trinidad.change.ChangeManager;
import org.apache.myfaces.trinidad.component.UIXComponent;
+import org.apache.myfaces.trinidad.component.UIXDocument;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
/**
* Subclass of UIComponentTag to add convenience methods,
* and optimize where appropriate.
@@ -83,8 +78,14 @@
public int doEndTag() throws JspException
{
UIComponent component = getComponentInstance();
- if (getCreated() || _forceApplyChanges)
- _applyChanges(getFacesContext(), component);
+
+ // Apply changes once we have a stable UIComponent subtree is completely
+ // created. End of document tag is a best bet.
+ if (component instanceof UIXDocument)
+ {
+ ChangeManager cm = RequestContext.getCurrentInstance().getChangeManager();
+ cm.applyComponentChangesForCurrentView(FacesContext.getCurrentInstance());
+ }
return super.doEndTag();
}
@@ -399,151 +400,6 @@
return list.toArray(new String[list.size()]);
}
- /**
- * Locate and return the nearest enclosing UIComponentClassicTagBase for a given tag if any;
- * otherwise, return null.
- * @param tag The tag to start the walk up from
- * @return The nearest enclosing UIXComponentELTag instance
- */
- private UIComponentClassicTagBase _getParentUIComponentClassicTagBase(
- UIComponentClassicTagBase tag)
- {
- if (tag == null)
- return null;
-
- Tag result = tag.getParent();
- while (result != null)
- {
- if (result instanceof UIComponentClassicTagBase)
- return (UIComponentClassicTagBase) result;
- result = result.getParent();
- }
- return null;
- }
-
- /**
- * Walks up the tree, starting from a supplied startTag and finds an enclosing tag matching the
- * supplied absolute idPath.
- * @param startTag The tag from where to start the tag tree walk up from.
- * @param idPath An array of id's that represents the absolute id of the enclosing tag.
- * @return The UIXComponentELTag that matches the absolute id if find was successful,
- * null otherwise.
- */
- private UIXComponentELTag _findEnclosingTag(
- UIXComponentELTag startTag,
- String[] idPath)
- {
- if (startTag == null || idPath == null || idPath.length == 0)
- return null;
-
- LinkedList<UIComponentClassicTagBase> enclosingTags =
- new LinkedList<UIComponentClassicTagBase>();
- // The last entry will be the id of the tag to be found.
- String targetId = idPath[idPath.length - 1];
-
- // Step 1: Move up and build a list of all enclosing tags for the startTag.
- for(UIComponentClassicTagBase currComponentTag = startTag;
- currComponentTag != null;
- currComponentTag = _getParentUIComponentClassicTagBase(currComponentTag))
- {
- enclosingTags.addFirst(currComponentTag);
- }
-
- // Bail out if we could not build a trace path of enclosing tags.
- if (enclosingTags.isEmpty())
- return null;
-
- // Step 2: Walk forward the list of enclosing tags to find the target.
- Iterator<UIComponentClassicTagBase> iter = enclosingTags.iterator();
-
- // Step 2a: If there are tags corresponding to NamingContainers in list, skip the expected
- // number of such NamingContainer tags.
- int namingContainerIndex = 0;
- for(UIComponentClassicTagBase currComponentTag = iter.next();
- currComponentTag != null;
- currComponentTag = iter.next())
- {
- UIComponent currComponent = currComponentTag.getComponentInstance();
-
- if (currComponent instanceof NamingContainer)
- {
- // If the id of this 'NamingContainer' tag does not match the next segment in sequence,
- // we would never be able to reach target, bail out.
- if (! currComponent.getId().equals(idPath[namingContainerIndex]))
- return null;
- else
- {
- namingContainerIndex++;
- if (namingContainerIndex == idPath.length - 1)
- break;
- }
- }
- }
-
- // Did not find all of our path elements, something very messed up.
- if (namingContainerIndex < idPath.length - 1)
- return null;
-
- // Step 2b: Look for the target tag from here on.
- for (UIComponentClassicTagBase currComponentTag = iter.next();
- currComponentTag != null;
- currComponentTag = iter.next())
- {
- if (targetId.equals(currComponentTag.getComponentInstance().getId()))
- {
- // If we are here, we reached the target, and it is very likely a UIXComponentELTag.
- return (currComponentTag instanceof UIXComponentELTag) ?
- (UIXComponentELTag)currComponentTag : null;
- }
- }
-
- // If we reached here, we could not find the target.
- return null;
- }
-
- private void _applyChanges(
- FacesContext facesContext,
- UIComponent uiComponent)
- {
- RequestContext afc = RequestContext.getCurrentInstance();
- Iterator<ComponentChange> changeIter =
- afc.getChangeManager().getComponentChanges(facesContext, uiComponent);
-
- if (changeIter == null)
- return;
- while (changeIter.hasNext())
- {
- ComponentChange change = changeIter.next();
-
- // If this is just a marker change, find and flag the target component.
- if (change instanceof ChangeMarker)
- {
- String id = ((ChangeMarker) change).getChangeTargetComponentScopedId();
- String[] idPath = id.split(String.valueOf(NamingContainer.SEPARATOR_CHAR));
- UIXComponentELTag targetTag = _findEnclosingTag(this, idPath);
- if (targetTag != null)
- targetTag._forceApplyChanges = true;
- }
- else
- {
- change.changeComponent(uiComponent);
-
- // In case this Change has added a new component/facet, the added
- // component could have its own Changes, that may need to be applied here.
- if (change instanceof AddComponentChange)
- {
- UIComponent newAddedComponent =
- ((AddComponentChange) change).getComponent();
-
- if (newAddedComponent != null)
- {
- _applyChanges(facesContext, newAddedComponent);
- }
- }
- }
- }
- }
-
private static final TrinidadLogger _LOG =
TrinidadLogger.createTrinidadLogger(UIXComponentELTag.class);
@@ -557,9 +413,6 @@
return sdf;
}
- // Use if change application needs to be forced on the tag regardless of whether the
- // corresponding component is newly created during tag execution.
- private boolean _forceApplyChanges;
private MethodExpression _attributeChangeListener;
private String _validationError;
}
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentTag.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentTag.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentTag.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UIXComponentTag.java Mon Nov 10 23:44:55 2008
@@ -24,13 +24,11 @@
import java.util.ArrayList;
import java.util.Date;
-import java.util.Iterator;
import javax.el.MethodExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
-import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;
@@ -40,14 +38,11 @@
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
-import org.apache.myfaces.trinidad.change.AddComponentChange;
-import org.apache.myfaces.trinidad.change.AttributeComponentChange;
-import org.apache.myfaces.trinidad.change.ComponentChange;
import org.apache.myfaces.trinidad.component.UIXComponent;
-import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.event.AttributeChangeEvent;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
/**
* Subclass of UIComponentTag to add convenience methods,
* and optimize where appropriate.
@@ -112,24 +107,6 @@
}
@Override
- public int doEndTag() throws JspException
- {
- UIComponent component = getComponentInstance();
- if (isSuppressed() && getCreated())
- _applyChanges(getFacesContext(), component);
- return super.doEndTag();
- }
-
- @Override
- protected void encodeBegin() throws java.io.IOException
- {
- UIComponent component = getComponentInstance();
- if (!isSuppressed() && getCreated())
- _applyChanges(getFacesContext(), component);
- super.encodeBegin();
- }
-
- @Override
protected final void setProperties(UIComponent component)
{
if (component instanceof UIViewRoot)
@@ -562,37 +539,6 @@
return list.toArray(new String[list.size()]);
}
- private static void _applyChanges(
- FacesContext facesContext,
- UIComponent uiComponent)
- {
- RequestContext afc = RequestContext.getCurrentInstance();
- Iterator<ComponentChange> changeIter =
- afc.getChangeManager().getComponentChanges(facesContext, uiComponent);
-
- if (changeIter == null)
- return;
- while (changeIter.hasNext())
- {
- ComponentChange change = changeIter.next();
-
- change.changeComponent(uiComponent);
-
- //pu: In case this Change has added a new component/facet, the added
- // component could have its own Changes, that may need to be applied here.
- if (change instanceof AddComponentChange)
- {
- UIComponent newAddedComponent =
- ( (AddComponentChange)change ).getComponent();
-
- if (newAddedComponent != null)
- {
- _applyChanges(facesContext, newAddedComponent);
- }
- }
- }
- }
-
private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(UIXComponentTag.class);
// We rely strictly on ISO 8601 formats
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts Mon Nov 10 23:44:55 2008
@@ -177,8 +177,8 @@
<!-- INVALID_INDEX -->
<resource key="INVALID_INDEX">Invalid index</resource>
- <!-- ATTEMP_ADD_DUPLICATE_ID -->
- <resource key="ATTEMP_ADD_DUPLICATE_ID">Attempt to add a duplicate ID {0}</resource>
+ <!-- ATTEMPT_ADD_CHILD_WITH_DUPLICATE_ID -->
+ <resource key="ATTEMPT_ADD_CHILD_WITH_DUPLICATE_ID">Adding a child when a child with same ID already exists. Old child will be removed and new child added. {0}</resource>
<!-- NO_NODE_SPECIFIED -->
<resource key="NO_NODE_SPECIFIED">No node specified</resource>
@@ -225,6 +225,27 @@
<!-- FACET_NAME_MUST_SPECIFIED -->
<resource key="FACET_NAME_MUST_SPECIFIED">Facet name must be specified</resource>
+ <!-- MOVABLE_CHILD_REQUIRED -->
+ <resource key="MOVABLE_CHILD_REQUIRED">Child component to be moved is required.</resource>
+
+ <!-- DESTINATION_CONTAINER_REQUIRED -->
+ <resource key="DESTINATION_CONTAINER_REQUIRED">Destination container component is required.</resource>
+
+ <!-- MOVE_PARTICIPANTS_WITHOUT_ID -->
+ <resource key="MOVE_PARTICIPANTS_WITHOUT_ID">One or more of the participating components in MoveChildComponentChange does not have id.</resource>
+
+ <!-- COMMON_PARENT_NOT_FOUND -->
+ <resource key="COMMON_PARENT_NOT_FOUND">Could not find a common parent between the movable child and destination container: {0}.</resource>
+
+ <!-- MOVABLE_CHILD_NOT_FOUND -->
+ <resource key="MOVABLE_CHILD_NOT_FOUND">Child to be moved could not be found: {0}.</resource>
+
+ <!-- DESTINATION_CONTAINER_NOT_FOUND -->
+ <resource key="DESTINATION_CONTAINER_NOT_FOUND">Destination container could not be found: {0}.</resource>
+
+ <!-- INSERT_BEFORE_NOT_FOUND -->
+ <resource key="INSERT_BEFORE_NOT_FOUND">Insert before component or node could not be found: {0}.</resource>
+
<!-- INDEX_SIZE -->
<resource key="INDEX_SIZE">index:{0} size:{1}</resource>
Modified: myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/change/NullChangeManager.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/change/NullChangeManager.java?rev=712972&r1=712971&r2=712972&view=diff
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/change/NullChangeManager.java (original)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/change/NullChangeManager.java Mon Nov 10 23:44:55 2008
@@ -18,14 +18,13 @@
*/
package org.apache.myfaces.trinidadinternal.change;
-import java.util.Iterator;
-
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.apache.myfaces.trinidad.change.ChangeManager;
import org.apache.myfaces.trinidad.change.ComponentChange;
+
/**
* An ChangeManager implementation that is all a no-op.
*
@@ -43,23 +42,14 @@
{
// do nothing
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator<ComponentChange> getComponentChanges(FacesContext facesContext,
- UIComponent uiComponent)
- {
- return null;
- }
-
+
/**
* {@inheritDoc}
+ * @param facesContext The FacesContext instance for the current request.
*/
@Override
- public Iterator<String> getComponentIdsWithChanges(FacesContext facesContext)
+ public void applyComponentChangesForCurrentView(FacesContext facesContext)
{
- return null;
+ //no-op
}
}