You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2016/11/23 01:36:27 UTC

svn commit: r1770904 [1/3] - in /myfaces/core/branches/2.3.x: api/src/main/java/javax/faces/ api/src/main/java/javax/faces/application/ api/src/main/java/javax/faces/component/search/ impl/src/main/java/org/apache/myfaces/application/ impl/src/main/jav...

Author: lu4242
Date: Wed Nov 23 01:36:27 2016
New Revision: 1770904

URL: http://svn.apache.org/viewvc?rev=1770904&view=rev
Log:
MYFACES-4075 SearchExpression API (working proposal)

Added:
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/ComponentNotFoundException.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/Markup.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContext.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContextFactory.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandler.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandlerWrapper.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHint.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionResolver.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchKeywordContext.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/AllSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ChildSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeComponentParentSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/FormSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/IdSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NamingContainerSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NextSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NoneSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ParentSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/PreviousSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/RootSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/SearchComponentUtils.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/SearchExpressionContextFactoryImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/SearchExpressionContextImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/SearchExpressionHandlerImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ThisSearchExpressionResolver.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/component/search/
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/component/search/SearchBean.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/component/search/SearchExpressionImplTest.java
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/resources/
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/resources/testComposite/
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/resources/testComposite/compositeActionSource.xhtml
      - copied, changed from r1757774, myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/compositeActionSource.xhtml
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/resources/testComposite/simpleActionSource.xhtml
      - copied unchanged from r1757774, myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleActionSource.xhtml
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/search1.xhtml
      - copied, changed from r1757774, myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/application/flow/flow1_1.xhtml
    myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/component/search/testCompositeActionSource.xhtml
      - copied unchanged from r1757774, myfaces/core/branches/2.3.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testCompositeActionSource.xhtml
Modified:
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/FactoryFinder.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/application/Application.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/DefaultFacesConfigurationProvider.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/FacesConfigDispenser.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/element/Factory.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/FactoryImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlLabelRenderer.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/spi/ServiceProviderFinder.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/UILeaf.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/application/ApplicationImplJsfTest.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlLabelRendererTest.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlMessageRendererTest.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/renderkit/html/HtmlMessagesRendererTest.java
    myfaces/core/branches/2.3.x/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletTestCase.java
    myfaces/core/branches/2.3.x/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessageRendererBase.java
    myfaces/core/branches/2.3.x/shared/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessagesRendererBase.java

Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/FactoryFinder.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/FactoryFinder.java?rev=1770904&r1=1770903&r2=1770904&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/FactoryFinder.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/FactoryFinder.java Wed Nov 23 01:36:27 2016
@@ -47,6 +47,7 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.faces.component.search.SearchExpressionContextFactory;
 
 /**
  * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
@@ -67,6 +68,8 @@ public final class FactoryFinder
     public static final String FLASH_FACTORY = "javax.faces.context.FlashFactory";
     public static final String FLOW_HANDLER_FACTORY = "javax.faces.flow.FlowHandlerFactory";
     public static final String CLIENT_WINDOW_FACTORY = "javax.faces.lifecycle.ClientWindowFactory";
+    public static final String SEARCH_EXPRESSION_CONTEXT_FACTORY = 
+            "javax.faces.component.search.SearchExpressionContextFactory";
 
     /**
      * used as a monitor for itself and _factories. Maps in this map are used as monitors for themselves and the
@@ -112,6 +115,7 @@ public final class FactoryFinder
         VALID_FACTORY_NAMES.add(FLASH_FACTORY);
         VALID_FACTORY_NAMES.add(FLOW_HANDLER_FACTORY);
         VALID_FACTORY_NAMES.add(CLIENT_WINDOW_FACTORY);
+        VALID_FACTORY_NAMES.add(SEARCH_EXPRESSION_CONTEXT_FACTORY);
         
         ABSTRACT_FACTORY_CLASSES.put(APPLICATION_FACTORY, ApplicationFactory.class);
         ABSTRACT_FACTORY_CLASSES.put(EXCEPTION_HANDLER_FACTORY, ExceptionHandlerFactory.class);
@@ -127,6 +131,7 @@ public final class FactoryFinder
         ABSTRACT_FACTORY_CLASSES.put(FLASH_FACTORY, FlashFactory.class);
         ABSTRACT_FACTORY_CLASSES.put(FLOW_HANDLER_FACTORY, FlowHandlerFactory.class);
         ABSTRACT_FACTORY_CLASSES.put(CLIENT_WINDOW_FACTORY, ClientWindowFactory.class);
+        ABSTRACT_FACTORY_CLASSES.put(SEARCH_EXPRESSION_CONTEXT_FACTORY, SearchExpressionContextFactory.class);
         try
         {
             ClassLoader classLoader;

Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/application/Application.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/application/Application.java?rev=1770904&r1=1770903&r2=1770904&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/application/Application.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/application/Application.java Wed Nov 23 01:36:27 2016
@@ -34,6 +34,8 @@ import javax.faces.FacesException;
 import javax.faces.component.UIComponent;
 import javax.faces.context.ExternalContext;
 import javax.faces.component.behavior.Behavior;
+import javax.faces.component.search.SearchExpressionHandler;
+import javax.faces.component.search.SearchExpressionResolver;
 import javax.faces.context.FacesContext;
 import javax.faces.convert.Converter;
 import javax.faces.el.MethodBinding;
@@ -1251,4 +1253,57 @@ public abstract class Application
         throw new UnsupportedOperationException();
 
     }
+    
+    public void addSearchExpressionResolver(SearchExpressionResolver resolver)
+    {
+        // The following concrete methods were added for JSF 1.2.  They supply default 
+        // implementations that throw UnsupportedOperationException.  
+        // This allows old Application implementations to still work.
+        Application application = getMyfacesApplicationInstance();
+        if (application != null)
+        {
+            application.addSearchExpressionResolver(resolver);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+    
+    public SearchExpressionResolver getSearchExpressionResolver()
+    {
+        Application application = getMyfacesApplicationInstance();
+        if (application != null)
+        {
+            return application.getSearchExpressionResolver();
+        }
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * @since 2.3
+     * @return 
+     */
+    public SearchExpressionHandler getSearchExpressionHandler()
+    {
+        Application application = getMyfacesApplicationInstance();
+        if (application != null)
+        {
+            return application.getSearchExpressionHandler();
+        }
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * @since 2.3
+     * @param searchExpressionHandler 
+     */
+    public void setSearchExpressionHandler(SearchExpressionHandler searchExpressionHandler)
+    {
+        Application application = getMyfacesApplicationInstance();
+        if (application != null)
+        {
+            application.setSearchExpressionHandler(searchExpressionHandler);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
 }

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/ComponentNotFoundException.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/ComponentNotFoundException.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/ComponentNotFoundException.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/ComponentNotFoundException.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,48 @@
+/*
+ * 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.search;
+
+import javax.faces.FacesException;
+
+/**
+ *
+ */
+public class ComponentNotFoundException extends FacesException
+{
+
+    public ComponentNotFoundException()
+    {
+        super();
+    }
+
+    public ComponentNotFoundException(String message)
+    {
+        super(message);
+    }
+
+    public ComponentNotFoundException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public ComponentNotFoundException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/Markup.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/Markup.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/Markup.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/Markup.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,27 @@
+/*
+ * 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.search;
+
+/**
+ * Components implementing this interface are ignored by @child(n) search keyword.
+ */
+public interface Markup
+{    
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContext.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContext.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContext.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,57 @@
+/*
+ * 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.search;
+
+import java.util.Set;
+import javax.faces.FactoryFinder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ */
+public abstract class SearchExpressionContext
+{
+    
+    public static SearchExpressionContext createSearchExpressionContext(FacesContext context, UIComponent source)
+    {
+        return createSearchExpressionContext(context, source, null, null);
+    }
+        
+    public static SearchExpressionContext createSearchExpressionContext(
+            FacesContext context,  UIComponent source, 
+            Set<SearchExpressionHint> expressionHints, Set<VisitHint> visitHints)
+    {
+        SearchExpressionContextFactory factory
+                = (SearchExpressionContextFactory) FactoryFinder.getFactory(
+                        FactoryFinder.SEARCH_EXPRESSION_CONTEXT_FACTORY);
+        return factory.getSearchExpressionContext(context, source, expressionHints, visitHints);
+    }
+
+    public abstract UIComponent getSource();
+
+    public abstract Set<VisitHint> getVisitHints();
+
+    public abstract Set<SearchExpressionHint> getExpressionHints();
+
+    public abstract FacesContext getFacesContext();
+    
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContextFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContextFactory.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContextFactory.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionContextFactory.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,40 @@
+/*
+ * 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.search;
+
+import java.util.Set;
+import javax.faces.FacesWrapper;
+import javax.faces.component.UIComponent;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ */
+public abstract class SearchExpressionContextFactory implements FacesWrapper<SearchExpressionContextFactory>
+{
+    public abstract SearchExpressionContext getSearchExpressionContext(
+            FacesContext context,  UIComponent source,  
+            Set<SearchExpressionHint> expressionHints, Set<VisitHint> visitHints);
+    
+    public SearchExpressionContextFactory getWrapped()
+    {
+        return null;
+    }
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandler.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandler.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandler.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,75 @@
+/*
+ * 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.search;
+
+import java.util.List;
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+
+/**
+ *
+ */
+public abstract class SearchExpressionHandler
+{
+
+    protected static final char[] EXPRESSION_SEPARATOR_CHARS = new char[]
+    {
+        ',', ' '
+    };
+    protected static final String KEYWORD_PREFIX = "@";
+
+    public abstract String resolveClientId(SearchExpressionContext searchExpressionContext, String expressions);
+    
+    public abstract List<String> resolveClientIds(
+            SearchExpressionContext searchExpressionContext, String expressions);
+    
+    public abstract void resolveComponent(SearchExpressionContext searchExpressionContext, String expression, 
+            ContextCallback callback);
+
+    public abstract void resolveComponents(SearchExpressionContext searchExpressionContext, String expressions, 
+            ContextCallback callback);
+    
+    public abstract void invokeOnComponentFromExpression(SearchExpressionContext searchExpressionContext,
+            UIComponent last, String expression, ContextCallback topCallback);
+
+    public void invokeOnComponentFromExpressions(SearchExpressionContext searchExpressionContext,
+            UIComponent last, String[] expressions, ContextCallback topCallback)
+    {
+        for (String expression : expressions)
+        {
+            invokeOnComponentFromExpression(searchExpressionContext, last, expression, topCallback);
+        }
+    }
+    
+    public abstract void applyKeyword(SearchExpressionContext searchExpressionContext, UIComponent last, 
+                             String command, ContextCallback topCallback);
+    
+    public abstract String[] splitExpressions(String expressions);
+    
+    public abstract List<UIComponent> findComponentFromExpression(SearchExpressionContext searchExpressionContext, 
+            UIComponent source, String topExpression);
+
+    public abstract List<UIComponent> applyKeyword(SearchExpressionContext searchExpressionContext, UIComponent last, 
+                             String command);
+
+    public abstract boolean isPassthroughExpression(SearchExpressionContext searchExpressionContext, String expression);
+    
+    public abstract boolean isValidExpression(SearchExpressionContext searchExpressionContext, String expression);
+    
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandlerWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandlerWrapper.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandlerWrapper.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHandlerWrapper.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,70 @@
+/*
+ * 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.search;
+
+import java.util.List;
+import javax.faces.FacesWrapper;
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+
+/**
+ *
+ */
+public abstract class SearchExpressionHandlerWrapper extends SearchExpressionHandler
+        implements FacesWrapper<SearchExpressionHandler>
+{
+
+    @Override
+    public abstract SearchExpressionHandler getWrapped();
+
+    @Override
+    public List<String> resolveClientIds(SearchExpressionContext searchExpressionContext, String expressions)
+    {
+        return getWrapped().resolveClientIds(searchExpressionContext, expressions);
+    }
+
+    @Override
+    public void resolveComponent(SearchExpressionContext searchExpressionContext, 
+            String expression, ContextCallback callback)
+    {
+        getWrapped().resolveComponent(searchExpressionContext, expression, callback);
+    }
+
+    @Override
+    public void invokeOnComponentFromExpression(SearchExpressionContext searchExpressionContext, 
+            UIComponent last, String expression, ContextCallback topCallback)
+    {
+        getWrapped().invokeOnComponentFromExpression(searchExpressionContext, last, expression, topCallback);
+    }
+
+    @Override
+    public void invokeOnComponentFromExpressions(SearchExpressionContext searchExpressionContext, 
+            UIComponent last, String[] expressions, ContextCallback topCallback)
+    {
+        getWrapped().invokeOnComponentFromExpressions(searchExpressionContext, last, expressions, topCallback);
+    }
+
+    @Override
+    public void applyKeyword(SearchExpressionContext searchExpressionContext, 
+            UIComponent last, String command, ContextCallback topCallback)
+    {
+        getWrapped().applyKeyword(searchExpressionContext, last, command, topCallback);
+    }
+
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHint.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHint.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHint.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionHint.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,38 @@
+/*
+ * 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.search;
+
+/**
+ *
+ */
+public enum SearchExpressionHint 
+{
+    
+    IGNORE_NO_RESULT,
+
+    PARENT_FALLBACK,
+    
+    RESOLVE_CLIENT_ID,
+    
+    RESOLVE_COMPONENT_LIST,
+    
+    RESOLVE_AJAX
+
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,66 @@
+/*
+ * 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.search;
+
+import javax.faces.component.UIComponent;
+
+/**
+ *
+ */
+public abstract class SearchExpressionResolver
+{
+    
+    public abstract void resolve(SearchKeywordContext keywordContext, UIComponent last, String keyword);
+    
+    /**
+     * Check if the keyword can be resolved by the current resolver
+     * 
+     * @param searchExpressionContext
+     * @param keyword
+     * @return 
+     */
+    public abstract boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword);
+    
+    /**
+     * A passthrough keyword is a keyword that according to the context does not require to be resolved on the server,
+     * and can be passed to the client
+     * 
+     * @param searchExpressionContext
+     * @param keyword
+     * @return 
+     */
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    /**
+     * A leaf keyword is a keyword that does not allow to be combined with keywords or id chains to the right.
+     * For example: @none:@parent.
+     * 
+     * @param searchExpressionContext
+     * @param keyword
+     * @return 
+     */
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+}

Added: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchKeywordContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchKeywordContext.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchKeywordContext.java (added)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/component/search/SearchKeywordContext.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,112 @@
+/*
+ * 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.search;
+
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ */
+public class SearchKeywordContext
+{
+    private SearchExpressionContext searchExpressionContext;
+    
+    private ContextCallback topCallback;
+    
+    private boolean commandResolved;
+    
+    private final FacesContext facesContext;
+    
+    public SearchKeywordContext(FacesContext facesContext)
+    {
+        this.facesContext = facesContext;
+    }
+
+    /**
+     * @return the facesContext
+     */
+    public FacesContext getFacesContext()
+    {
+        return facesContext;
+    }
+    
+    public void invokeContextCallback(FacesContext context, UIComponent target)
+    {
+        try
+        {
+            this.getTopCallback().invokeContextCallback(context, target);
+        }
+        finally
+        {
+            this.setCommandResolved(true);
+        }
+    }
+
+    /**
+     * @return the topCallback
+     */
+    public ContextCallback getTopCallback()
+    {
+        return topCallback;
+    }
+
+    /**
+     * @return the commandResolved
+     */
+    public boolean isCommandResolved()
+    {
+        return commandResolved;
+    }
+
+    /**
+     * @param commandResolved the commandResolved to set
+     */
+    public void setCommandResolved(boolean commandResolved)
+    {
+        this.commandResolved = commandResolved;
+    }
+
+    /**
+     * @param topCallback the topCallback to set
+     */
+    public void setTopCallback(ContextCallback topCallback)
+    {
+        this.topCallback = topCallback;
+    }
+
+    /**
+     * @return the searchExpressionContext
+     */
+    public SearchExpressionContext getSearchExpressionContext()
+    {
+        return searchExpressionContext;
+    }
+
+    /**
+     * @param searchExpressionContext the searchExpressionContext to set
+     */
+    public void setSearchExpressionContext(SearchExpressionContext searchExpressionContext)
+    {
+        this.searchExpressionContext = searchExpressionContext;
+    }
+
+}

Modified: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java?rev=1770904&r1=1770903&r2=1770904&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java Wed Nov 23 01:36:27 2016
@@ -62,6 +62,8 @@ import javax.faces.component.UIOutput;
 import javax.faces.component.UIViewRoot;
 import javax.faces.component.behavior.Behavior;
 import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.search.SearchExpressionHandler;
+import javax.faces.component.search.SearchExpressionResolver;
 import javax.faces.context.FacesContext;
 import javax.faces.convert.Converter;
 import javax.faces.convert.DateTimeConverter;
@@ -94,6 +96,20 @@ import org.apache.myfaces.application.cd
 import org.apache.myfaces.cdi.util.ExternalArtifactResolver;
 import org.apache.myfaces.application.cdi.ValidatorWrapper;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.component.search.AllSearchExpressionResolver;
+import org.apache.myfaces.component.search.ChildSearchExpressionResolver;
+import org.apache.myfaces.component.search.CompositeComponentParentSearchExpressionResolver;
+import org.apache.myfaces.component.search.CompositeSearchExpressionResolver;
+import org.apache.myfaces.component.search.FormSearchExpressionResolver;
+import org.apache.myfaces.component.search.IdSearchExpressionResolver;
+import org.apache.myfaces.component.search.NamingContainerSearchExpressionResolver;
+import org.apache.myfaces.component.search.NextSearchExpressionResolver;
+import org.apache.myfaces.component.search.NoneSearchExpressionResolver;
+import org.apache.myfaces.component.search.ParentSearchExpressionResolver;
+import org.apache.myfaces.component.search.PreviousSearchExpressionResolver;
+import org.apache.myfaces.component.search.RootSearchExpressionResolver;
+import org.apache.myfaces.component.search.SearchExpressionHandlerImpl;
+import org.apache.myfaces.component.search.ThisSearchExpressionResolver;
 import org.apache.myfaces.config.RuntimeConfig;
 import org.apache.myfaces.config.element.Property;
 import org.apache.myfaces.config.element.ResourceBundle;
@@ -233,6 +249,10 @@ public class ApplicationImpl extends App
     
     private final ExternalArtifactResolver _externalArtifactResolver;
     
+    private SearchExpressionHandler _searchExpressionHandler;
+    
+    private SearchExpressionResolver _searchExpressionResolver;
+    
     /**
      * Represents semantic null in _componentClassMap. 
      */
@@ -276,6 +296,7 @@ public class ApplicationImpl extends App
         _elContextListeners = new ArrayList<ELContextListener>();
         _resourceHandler = new ResourceHandlerImpl();
         _flowHandler = new FlowHandlerImpl();
+        _searchExpressionHandler = new SearchExpressionHandlerImpl();
         _runtimeConfig = runtimeConfig;
 
         if (log.isLoggable(Level.FINEST))
@@ -2874,4 +2895,76 @@ public class ApplicationImpl extends App
         }
         return _lazyLoadConfigObjects;
     }
+    
+    
+    @Override
+    public final void setSearchExpressionHandler(SearchExpressionHandler searchExpressionHandler)
+    {
+        checkNull(searchExpressionHandler, "searchExpressionHandler");
+
+        if(isFirstRequestProcessed())
+        {
+            throw new IllegalStateException(
+                    "setFlowHandler may not be executed after a lifecycle request has been completed");
+        }
+        _searchExpressionHandler = searchExpressionHandler;
+    }
+
+    @Override
+    public final SearchExpressionHandler getSearchExpressionHandler()
+    {
+        return _searchExpressionHandler;
+    }
+
+    @Override
+    public SearchExpressionResolver getSearchExpressionResolver()
+    {
+        // we don't need synchronization here since it is ok to have multiple
+        // instances of the elresolver
+        if (_searchExpressionResolver == null)
+        {
+            _searchExpressionResolver = createSearchExpressionResolver();
+        }
+        return _searchExpressionResolver;
+    }
+    
+    private SearchExpressionResolver createSearchExpressionResolver()
+    {
+        // Chain of responsibility pattern
+        CompositeSearchExpressionResolver baseResolver = new CompositeSearchExpressionResolver();
+        
+        for (SearchExpressionResolver child : getRuntimeConfig().getApplicationSearchExpressionResolvers())
+        {
+            baseResolver.add(child);
+        }
+        
+        baseResolver.add(new ThisSearchExpressionResolver());
+        baseResolver.add(new ParentSearchExpressionResolver());
+        baseResolver.add(new ChildSearchExpressionResolver());
+        baseResolver.add(new CompositeComponentParentSearchExpressionResolver());
+        baseResolver.add(new FormSearchExpressionResolver());
+        baseResolver.add(new NamingContainerSearchExpressionResolver());
+        baseResolver.add(new NextSearchExpressionResolver());
+        baseResolver.add(new NoneSearchExpressionResolver());
+        baseResolver.add(new PreviousSearchExpressionResolver());
+        baseResolver.add(new RootSearchExpressionResolver());
+        baseResolver.add(new IdSearchExpressionResolver());
+        baseResolver.add(new AllSearchExpressionResolver());
+        
+        return baseResolver;
+    }
+
+    @Override
+    public void addSearchExpressionResolver(SearchExpressionResolver resolver)
+    {
+        if (isFirstRequestProcessed())
+        {
+            throw new IllegalStateException(
+                    "It is illegal to add a search expression resolver after the first request is processed");
+        }
+        if (resolver != null)
+        {
+            _runtimeConfig.addApplicationSearchExpressionResolver(resolver);
+        }
+    }
 }

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/AllSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/AllSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/AllSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/AllSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class AllSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String ALL_KEYWORD = "all";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(ALL_KEYWORD))
+        {
+            UIComponent parent = last.getParent();
+
+            while (parent.getParent() != null)
+            {
+                parent = parent.getParent();
+            }
+
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), parent);
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return ALL_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return true;
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ChildSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ChildSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ChildSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ChildSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.component.search;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.Markup;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class ChildSearchExpressionResolver extends SearchExpressionResolver
+{
+
+    public static final String CHILD_KEYWORD = "child";
+
+    private static final Pattern PATTERN = Pattern.compile("child\\((\\d+)\\)");
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.length() > 6 && 
+                command.substring(0, CHILD_KEYWORD.length()).equalsIgnoreCase(CHILD_KEYWORD))
+        {
+            try
+            {
+                Matcher matcher = PATTERN.matcher(command);
+
+                if (matcher.matches())
+                {
+
+                    int childNumber = Integer.parseInt(matcher.group(1));
+
+                    if (childNumber + 1 > last.getChildCount())
+                    {
+                        throw new FacesException("Component with clientId \""
+                                + last.getClientId(expressionContext.getFacesContext()) 
+                                + "\" has fewer children as \"" + 
+                                  childNumber + "\". Expression: \"" + command + "\"");
+                    }
+
+                    List<UIComponent> list = last.getChildren();
+                    int count = 0;
+                    for (int i = 0; i < last.getChildCount(); i++)
+                    {
+                        if (! (list.get(i) instanceof Markup))
+                        {
+                            count++;
+                        }
+                        if (count == childNumber)
+                        {
+                            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), 
+                                    last.getChildren().get(childNumber));
+                            break;
+                        }
+                    }
+                    if (count < childNumber)
+                    {
+                        throw new FacesException("Component with clientId \""
+                                + last.getClientId(expressionContext.getFacesContext()) 
+                                + "\" has fewer children as \"" + 
+                                  childNumber + "\". Expression: \"" + command + "\"");
+                    }
+                }
+                else
+                {
+                    throw new FacesException(
+                            "Expression does not match following pattern @child(n). Expression: \"" + command + "\"");
+                }
+
+            }
+            catch (Exception e)
+            {
+                throw new FacesException(
+                        "Expression does not match following pattern @child(n). Expression: \"" + command + "\"", e);
+            }
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String command)
+    {
+        if (command != null && command.length() > 6 && 
+                command.substring(0, CHILD_KEYWORD.length()).equalsIgnoreCase(CHILD_KEYWORD))
+        {
+            try
+            {
+                Matcher matcher = PATTERN.matcher(command);
+
+                if (matcher.matches())
+                {
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            catch (Exception e)
+            {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeComponentParentSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeComponentParentSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeComponentParentSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeComponentParentSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class CompositeComponentParentSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String COMPOSITE_KEYWORD = "composite";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(COMPOSITE_KEYWORD))
+        {
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), 
+                    UIComponent.getCompositeComponentParent(last));
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return COMPOSITE_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    } 
+    
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/CompositeSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class CompositeSearchExpressionResolver extends SearchExpressionResolver
+{
+    private int size;
+
+    private SearchExpressionResolver[] resolvers;
+    
+    public CompositeSearchExpressionResolver()
+    {
+        this.size = 0;
+        this.resolvers = new SearchExpressionResolver[2];
+    }
+    
+    public void add(SearchExpressionResolver elResolver) 
+    {
+        if (elResolver == null) 
+        {
+            throw new NullPointerException();
+        }
+
+        if (this.size >= this.resolvers.length) 
+        {
+            SearchExpressionResolver[] nr = new SearchExpressionResolver[this.size * 2];
+            System.arraycopy(this.resolvers, 0, nr, 0, this.size);
+            this.resolvers = nr;
+        }
+        this.resolvers[this.size++] = elResolver;
+    }
+
+    @Override
+    public void resolve(SearchKeywordContext context, UIComponent last, String command)
+    {
+        context.setCommandResolved(false);
+        int sz = this.size;
+        Object result = null;
+        for (int i = 0; i < sz; i++) 
+        {
+            this.resolvers[i].resolve(context, last, command);
+            if (context.isCommandResolved()) 
+            {
+                return;
+            }
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        int sz = this.size;
+        for (int i = 0; i < sz; i++) 
+        {
+            if (this.resolvers[i].matchKeyword(searchExpressionContext, keyword))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        int sz = this.size;
+        for (int i = 0; i < sz; i++) 
+        {
+            if (this.resolvers[i].matchKeyword(searchExpressionContext, keyword))
+            {
+                return this.resolvers[i].isPassthroughKeyword(searchExpressionContext, keyword);
+            }
+        }
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        int sz = this.size;
+        for (int i = 0; i < sz; i++) 
+        {
+            if (this.resolvers[i].matchKeyword(searchExpressionContext, keyword))
+            {
+                return this.resolvers[i].isLeafKeyword(searchExpressionContext, keyword);
+            }
+        }
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/FormSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/FormSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/FormSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/FormSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchExpressionHint;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class FormSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String FORM_KEYWORD = "form";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(FORM_KEYWORD))
+        {
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), closest(UIForm.class, last));
+        }
+    }
+    
+    private static <T> T closest(Class<T> type, UIComponent base) 
+    {
+        UIComponent parent = base.getParent();
+
+        while (parent != null) 
+        {
+            if (type.isAssignableFrom(parent.getClass())) 
+            {
+                return (T) parent;
+            }
+
+            parent = parent.getParent();
+        }
+
+        return null;
+    }    
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return FORM_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        if (searchExpressionContext.getExpressionHints() != null &&
+            searchExpressionContext.getExpressionHints().contains(SearchExpressionHint.RESOLVE_AJAX))
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/IdSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/IdSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/IdSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/IdSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.component.search;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.faces.FacesException;
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchExpressionHint;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitResult;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ */
+public class IdSearchExpressionResolver extends SearchExpressionResolver
+{
+
+    public static final String ID_KEYWORD = "id";
+
+    private static final Pattern PATTERN = Pattern.compile("id\\((\\w+)\\)");
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.length() > 4
+                && command.substring(0, 2).equalsIgnoreCase(ID_KEYWORD) && command.charAt(2) == '(')
+        {
+            final String targetId = extractId(command);
+            if (expressionContext.getSearchExpressionContext().getExpressionHints() != null
+                    && expressionContext.getSearchExpressionContext().getExpressionHints().contains(
+                            SearchExpressionHint.RESOLVE_COMPONENT_LIST))
+            {
+                // Avoid visit tree because in this case we need real component instances.
+                // This means components inside UIData will not be scanned. 
+                withId(expressionContext.getFacesContext(), targetId, last, expressionContext.getTopCallback());
+                expressionContext.setCommandResolved(true);
+            }
+            else
+            {
+                last.visitTree(
+                        VisitContext.createVisitContext(expressionContext.getFacesContext(), null,
+                                expressionContext.getSearchExpressionContext().getVisitHints()),
+                        new VisitCallback()
+                        {
+                            @Override
+                            public VisitResult visit(VisitContext context, UIComponent target)
+                            {
+                                if (targetId.equals(target.getId()))
+                                {
+                                    expressionContext.invokeContextCallback(
+                                            expressionContext.getFacesContext(), target);
+                                    return VisitResult.COMPLETE;
+                                }
+                                else
+                                {
+                                    return VisitResult.ACCEPT;
+                                }
+                            }
+                        });
+            }
+        }
+    }
+
+    protected String extractId(String expression)
+    {
+        try
+        {
+            Matcher matcher = PATTERN.matcher(expression);
+            if (matcher.matches())
+            {
+                return matcher.group(1);
+            }
+            else
+            {
+                throw new FacesException("Expression does not match following pattern @id(id). Expression: \""
+                        + expression + "\"");
+            }
+
+        }
+        catch (Exception e)
+        {
+            throw new FacesException("Expression does not match following pattern @id(id). Expression: \""
+                    + expression + "\"", e);
+        }
+    }
+
+    private static void withId(FacesContext context, String id, UIComponent base, ContextCallback callback)
+    {
+
+        if (id.equals(base.getId()))
+        {
+            callback.invokeContextCallback(context, base);
+        }
+
+        if (base.getFacetCount() > 0)
+        {
+            for (UIComponent facet : base.getFacets().values())
+            {
+                withId(context, id, facet, callback);
+            }
+        }
+
+        if (base.getChildCount() > 0)
+        {
+            for (int i = 0, childCount = base.getChildCount(); i < childCount; i++)
+            {
+                UIComponent child = base.getChildren().get(i);
+                withId(context, id, child, callback);
+            }
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String command)
+    {
+        if (command != null && command.length() > 6 && 
+                command.substring(0, ID_KEYWORD.length()).equalsIgnoreCase(ID_KEYWORD))
+        {
+            try
+            {
+                Matcher matcher = PATTERN.matcher(command);
+
+                if (matcher.matches())
+                {
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            catch (Exception e)
+            {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NamingContainerSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NamingContainerSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NamingContainerSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NamingContainerSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class NamingContainerSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String NAMING_CONTAINER_KEYWORD = "namingcontainer";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(NAMING_CONTAINER_KEYWORD))
+        {
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), 
+                    (UIComponent) closest(NamingContainer.class, last));
+        }
+    }
+    
+    private static <T> T closest(Class<T> type, UIComponent base) 
+    {
+        UIComponent parent = base.getParent();
+
+        while (parent != null) 
+        {
+            if (type.isAssignableFrom(parent.getClass())) 
+            {
+                return (T) parent;
+            }
+
+            parent = parent.getParent();
+        }
+
+        return null;
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return NAMING_CONTAINER_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NextSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NextSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NextSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NextSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import java.util.List;
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class NextSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String NEXT_KEYWORD = "next";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(NEXT_KEYWORD))
+        {
+            UIComponent parent = last.getParent();
+            if (parent.getChildCount() > 1) 
+            {
+                    List<UIComponent> children = parent.getChildren();
+                    int index = children.indexOf(last);
+
+                    if (index < parent.getChildCount() - 1)
+                    {
+                        expressionContext.invokeContextCallback(expressionContext.getFacesContext(), 
+                                children.get(index + 1));
+                    }
+            }
+            expressionContext.setCommandResolved(true);
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return NEXT_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NoneSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NoneSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NoneSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/NoneSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class NoneSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String NONE_KEYWORD = "none";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(NONE_KEYWORD))
+        {
+            expressionContext.setCommandResolved(true);
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return NONE_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return true;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ParentSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ParentSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ParentSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/ParentSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class ParentSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String PARENT_KEYWORD = "parent";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(PARENT_KEYWORD))
+        {
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), last.getParent());
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return PARENT_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/PreviousSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/PreviousSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/PreviousSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/PreviousSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import java.util.List;
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class PreviousSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String PREVIOUS_KEYWORD = "previous";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(PREVIOUS_KEYWORD))
+        {
+            UIComponent parent = last.getParent();
+
+            if (parent.getChildCount() > 1)
+            {
+                List<UIComponent> children = parent.getChildren();
+                int index = children.indexOf(last);
+
+                if (index > 0)
+                {
+                    expressionContext.invokeContextCallback(
+                            expressionContext.getFacesContext(), children.get(index - 1));
+                }
+            }
+            expressionContext.setCommandResolved(true);
+        }
+    }
+    
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return PREVIOUS_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/RootSearchExpressionResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/RootSearchExpressionResolver.java?rev=1770904&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/RootSearchExpressionResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/search/RootSearchExpressionResolver.java Wed Nov 23 01:36:27 2016
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.component.search;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.search.SearchExpressionContext;
+import javax.faces.component.search.SearchKeywordContext;
+import javax.faces.component.search.SearchExpressionResolver;
+
+/**
+ *
+ */
+public class RootSearchExpressionResolver extends SearchExpressionResolver
+{
+    public static final String ROOT_KEYWORD = "root";
+
+    @Override
+    public void resolve(SearchKeywordContext expressionContext, UIComponent last, String command)
+    {
+        if (command != null && command.equalsIgnoreCase(ROOT_KEYWORD))
+        {
+            expressionContext.invokeContextCallback(expressionContext.getFacesContext(), 
+                    expressionContext.getFacesContext().getViewRoot());
+        }
+    }
+
+    @Override
+    public boolean matchKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return ROOT_KEYWORD.equalsIgnoreCase(keyword);
+    }
+
+    @Override
+    public boolean isPassthroughKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+    
+    @Override
+    public boolean isLeafKeyword(SearchExpressionContext searchExpressionContext, String keyword)
+    {
+        return false;
+    }
+
+}