Permalink
Browse files

MYFACES-3660 Component resource added using @ResourceDependency annot…

…ation from a facelet component should have an id defined by facelets

git-svn-id: https://svn.apache.org/repos/asf/myfaces/core/trunk@1417719 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent 760b53e commit ed8bb3f2d91fa868a5c6e8696898e0498e938b94 Leonardo Uribe committed Dec 6, 2012
@@ -116,6 +116,9 @@
private static final String JAVAX_FACES_LOCATION_BODY = "javax_faces_location_body";
private static final String JAVAX_FACES_LOCATION_FORM = "javax_faces_location_form";
+ private transient boolean _resourceDependencyUniqueId;
+ private transient Map<String,Object> _attributesMap;
+
/**
* Construct an instance of the UIViewRoot.
*/
@@ -343,10 +346,20 @@ public String createUniqueId(FacesContext context, String seed)
// UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
if(seed==null)
{
- Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
- uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
- getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
- return bld.append(UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
+ if (isResourceDependencyUniqueId())
+ {
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.resourceDependencyUniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.resourceDependencyUniqueIdCounter, (uniqueIdCounter+1L));
+ return bld.append(UNIQUE_ID_PREFIX).append("__rd_").append(uniqueIdCounter).toString();
+ }
+ else
+ {
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
+ return bld.append(UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
+ }
}
// Optionally, a unique seed value can be supplied by component creators which
// should be included in the generated unique id.
@@ -1234,6 +1247,32 @@ public void setAfterPhaseListener(MethodExpression afterPhaseListener)
getStateHelper().put(PropertyKeys.afterPhaseListener, afterPhaseListener);
}
+ @Override
+ public Map<String, Object> getAttributes()
+ {
+ if (_attributesMap == null)
+ {
+ _attributesMap = new _ViewAttributeMap(this, super.getAttributes());
+ }
+ return _attributesMap;
+ }
+
+ /**
+ * Indicates if the component is created when facelets builds the view and
+ * is caused by the presence of a ResourceDependency annotation.
+ *
+ * @return the _resourceDependencyUniqueId
+ */
+ boolean isResourceDependencyUniqueId()
+ {
+ return _resourceDependencyUniqueId;
+ }
+
+ void setResourceDependencyUniqueId(boolean resourceDependencyUniqueId)
+ {
+ this._resourceDependencyUniqueId = resourceDependencyUniqueId;
+ }
+
enum PropertyKeys
{
afterPhaseListener
@@ -1243,6 +1282,7 @@ public void setAfterPhaseListener(MethodExpression afterPhaseListener)
, renderKitId
, viewId
, uniqueIdCounter
+ , resourceDependencyUniqueIdCounter
}
@Override
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package javax.faces.component;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+class _ViewAttributeMap implements Map<String, Object>
+{
+ //private static final String RESET_SAVE_STATE_MODE_KEY =
+ // "oam.view.resetSaveStateMode";
+
+ /**
+ * Key under UIViewRoot to generated unique ids for components added
+ * by @ResourceDependency effect.
+ */
+ private static final String RESOURCE_DEPENDENCY_UNIQUE_ID_KEY =
+ "oam.view.resourceDependencyUniqueId";
+ private static final String UNIQUE_ID_COUNTER_KEY =
+ "oam.view.uniqueIdCounter";
+
+ private Map<String, Object> _delegate;
+ private UIViewRoot _root;
+
+ public _ViewAttributeMap(UIViewRoot root, Map<String, Object> delegate)
+ {
+ this._delegate = delegate;
+ this._root = root;
+ }
+
+ public int size()
+ {
+ return _delegate.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return _delegate.isEmpty();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return _delegate.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return _delegate.containsValue(value);
+ }
+
+ public Object get(Object key)
+ {
+ checkKey(key);
+ int keyLength = ((String)key).length();
+ /*
+ if (RESET_SAVE_STATE_MODE_KEY.length() == keyLength
+ && RESET_SAVE_STATE_MODE_KEY.equals(key))
+ {
+ return _root.getResetSaveStateMode();
+ }*/
+ if (RESOURCE_DEPENDENCY_UNIQUE_ID_KEY.length() == keyLength
+ && RESOURCE_DEPENDENCY_UNIQUE_ID_KEY.equals(key))
+ {
+ return _root.isResourceDependencyUniqueId();
+ }
+ if (UNIQUE_ID_COUNTER_KEY.length() == keyLength
+ && UNIQUE_ID_COUNTER_KEY.equals(key))
+ {
+ return _root.getStateHelper().get(UIViewRoot.PropertyKeys.uniqueIdCounter);
+ }
+ return _delegate.get(key);
+ }
+
+ public Object put(String key, Object value)
+ {
+ int keyLength = ((String)key).length();
+
+ /*
+ if (RESET_SAVE_STATE_MODE_KEY.length() == keyLength
+ && RESET_SAVE_STATE_MODE_KEY.equals(key))
+ {
+ Integer b = _root.getResetSaveStateMode();
+ _root.setResetSaveStateMode(value == null ? 0 : (Integer) value);
+ return b;
+ }*/
+ if (RESOURCE_DEPENDENCY_UNIQUE_ID_KEY.length() == keyLength
+ && RESOURCE_DEPENDENCY_UNIQUE_ID_KEY.equals(key))
+ {
+ boolean b = _root.isResourceDependencyUniqueId();
+ _root.setResourceDependencyUniqueId(value == null ? false : (Boolean) value);
+ return b;
+ }
+ if (UNIQUE_ID_COUNTER_KEY.length() == keyLength
+ && UNIQUE_ID_COUNTER_KEY.equals(key))
+ {
+ Long v = (Long) _root.getStateHelper().get(UIViewRoot.PropertyKeys.uniqueIdCounter);
+ _root.getStateHelper().put(UIViewRoot.PropertyKeys.uniqueIdCounter, value);
+ return v;
+ }
+ return _delegate.put(key, value);
+ }
+
+ public Object remove(Object key)
+ {
+ return _delegate.remove(key);
+ }
+
+ public void putAll(Map<? extends String, ? extends Object> m)
+ {
+ _delegate.putAll(m);
+ }
+
+ public void clear()
+ {
+ _delegate.clear();
+ }
+
+ public Set<String> keySet()
+ {
+ return _delegate.keySet();
+ }
+
+ public Collection<Object> values()
+ {
+ return _delegate.values();
+ }
+
+ public Set<Entry<String, Object>> entrySet()
+ {
+ return _delegate.entrySet();
+ }
+
+ public boolean equals(Object o)
+ {
+ return _delegate.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return _delegate.hashCode();
+ }
+
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ private void checkKey(Object key)
+ {
+ if (key == null)
+ {
+ throw new NullPointerException("key");
+ }
+ if (!(key instanceof String))
+ {
+ throw new ClassCastException("key is not a String");
+ }
+ }
+}
@@ -104,6 +104,7 @@
import org.apache.myfaces.lifecycle.LifecycleImpl;
import org.apache.myfaces.shared.config.MyfacesConfig;
import org.apache.myfaces.shared.util.ClassUtils;
+import org.apache.myfaces.view.facelets.FaceletCompositionContext;
import org.apache.myfaces.view.facelets.el.ELText;
/**
@@ -157,6 +158,14 @@
private static final boolean LAZY_LOAD_CONFIG_OBJECTS_DEFAULT_VALUE = true;
private Boolean _lazyLoadConfigObjects = null;
+
+ /**
+ * Key under UIViewRoot to generated unique ids for components added
+ * by @ResourceDependency effect.
+ */
+ private static final String RESOURCE_DEPENDENCY_UNIQUE_ID_KEY =
+ "oam.view.resourceDependencyUniqueId";
+
// ~ Instance fields
// --------------------------------------------------------------------------
// --
@@ -1798,6 +1807,50 @@ else if (dependencyList.isEmpty())
rvc.setClassProcessed(inspectedClass);
}
}
+
+ /**
+ * If the ResourceDependency component is created under facelets processing, it should receive
+ * an special unique component id. This method check if there is a FaceletCompositionContext
+ * and if that so, set the id. Components added by the effect of ResourceDependency are special,
+ * because they do not have state, but they depends on the view structure, so with PSS,
+ * each time the view is built they are "recalculated", so they work as if they were transient
+ * components that needs to be created at each request, but there are some cases were the
+ * components needs to be saved and restored fully. If a component is created outside facelets
+ * control (render response phase) it is expected to use the default implementation of
+ * createUniqueId(), but in that case, note that this happens after markInitialState() is
+ * called, and the component in this case is saved and restored fully, as expected.
+ *
+ * This code cannot be called from facelets component tag handler, because in cases where a
+ * component subtree is created using binding property, facelets lost control over component
+ * creation and delegates it to the user, but since the binding code is executed each time the
+ * view is created, the effect over ResourceDependency persists and the binding code takes into
+ * account in the recalculation step, even if later the node related to the binding property
+ * is dropped and recreated from the state fully.
+ *
+ * @param facesContext
+ * @param component
+ */
+ private void setResourceIdOnFaceletsMode(FacesContext facesContext, UIComponent component)
+ {
+ if (component.getId() == null)
+ {
+ FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(facesContext);
+ if (mctx != null)
+ {
+ UIViewRoot root = facesContext.getViewRoot();
+ root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.TRUE);
+ try
+ {
+ String uid = root.createUniqueId(facesContext, null);
+ component.setId(uid);
+ }
+ finally
+ {
+ root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.FALSE);
+ }
+ }
+ }
+ }
private void _handleAttachedResourceDependency(FacesContext context, ResourceDependency annotation)
{
@@ -1826,6 +1879,10 @@ private void _handleAttachedResourceDependency(FacesContext context, ResourceDep
// Call setRendererType on the UIOutput instance, passing the renderer-type.
output.setRendererType(rendererType);
+ // If the @ResourceDependency was done inside facelets processing,
+ // call setId() and set a proper id from facelets
+ setResourceIdOnFaceletsMode(context, output);
+
// Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
Map<String, Object> attributes = output.getAttributes();
@@ -2301,6 +2358,10 @@ private void _handleResourceDependency(FacesContext context, UIComponent compone
// Call setRendererType on the UIOutput instance, passing the renderer-type.
output.setRendererType(rendererType);
+
+ // If the @ResourceDependency was done inside facelets processing,
+ // call setId() and set a proper id from facelets
+ setResourceIdOnFaceletsMode(context, output);
// Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
Map<String, Object> attributes = output.getAttributes();
Oops, something went wrong.

0 comments on commit ed8bb3f

Please sign in to comment.