View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.component.search;
20  
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  import javax.faces.FacesException;
24  import javax.faces.component.ContextCallback;
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.search.SearchExpressionContext;
27  import javax.faces.component.search.SearchExpressionHint;
28  import javax.faces.component.search.SearchKeywordContext;
29  import javax.faces.component.search.SearchKeywordResolver;
30  import javax.faces.component.visit.VisitCallback;
31  import javax.faces.component.visit.VisitContext;
32  import javax.faces.component.visit.VisitResult;
33  import javax.faces.context.FacesContext;
34  
35  /**
36   *
37   */
38  public class IdSearchKeywordResolver extends SearchKeywordResolver
39  {
40  
41      public static final String ID_KEYWORD = "id";
42  
43      private static final Pattern PATTERN = Pattern.compile("id\\((\\w+)\\)");
44  
45      @Override
46      public void resolve(SearchKeywordContext expressionContext, UIComponent current, String keyword)
47      {
48          FacesContext facesContext = expressionContext.getSearchExpressionContext().getFacesContext();
49          
50          final String targetId = extractId(keyword);
51          if (expressionContext.getSearchExpressionContext().getExpressionHints() != null
52                  && expressionContext.getSearchExpressionContext().getExpressionHints().contains(
53                          SearchExpressionHint.SKIP_VIRTUAL_COMPONENTS))
54          {
55              // Avoid visit tree because in this case we need real component instances.
56              // This means components inside UIData will not be scanned. 
57              withId(facesContext, targetId, current, expressionContext.getCallback());
58              expressionContext.setKeywordResolved(true);
59          }
60          else
61          {
62              current.visitTree(
63                      VisitContext.createVisitContext(facesContext, null,
64                              expressionContext.getSearchExpressionContext().getVisitHints()),
65                      new VisitCallback()
66                      {
67                          @Override
68                          public VisitResult visit(VisitContext context, UIComponent target)
69                          {
70                              if (targetId.equals(target.getId()))
71                              {
72                                  expressionContext.invokeContextCallback(target);
73                                  
74                                  if (expressionContext.getSearchExpressionContext().getExpressionHints() != null
75                                          && expressionContext.getSearchExpressionContext().getExpressionHints().contains(
76                                                  SearchExpressionHint.RESOLVE_SINGLE_COMPONENT))
77                                  {
78                                      return VisitResult.COMPLETE;
79                                  }
80                                  
81                                  return VisitResult.ACCEPT;
82                              }
83                              else
84                              {
85                                  return VisitResult.ACCEPT;
86                              }
87                          }
88                      });
89          }
90      }
91  
92      protected String extractId(String expression)
93      {
94          Matcher matcher = PATTERN.matcher(expression);
95          if (matcher.matches())
96          {
97              return matcher.group(1);
98          }
99          else
100         {
101             throw new FacesException("Expression does not match following pattern @id(id). Expression: \""
102                     + expression + "\"");
103         }
104     }
105 
106     private static void withId(FacesContext context, String id, UIComponent base, ContextCallback callback)
107     {
108         if (id.equals(base.getId()))
109         {
110             callback.invokeContextCallback(context, base);
111         }
112 
113         if (base.getFacetCount() > 0)
114         {
115             for (UIComponent facet : base.getFacets().values())
116             {
117                 withId(context, id, facet, callback);
118             }
119         }
120 
121         if (base.getChildCount() > 0)
122         {
123             for (int i = 0, childCount = base.getChildCount(); i < childCount; i++)
124             {
125                 UIComponent child = base.getChildren().get(i);
126                 withId(context, id, child, callback);
127             }
128         }
129     }
130     
131     @Override
132     public boolean isResolverForKeyword(SearchExpressionContext searchExpressionContext, String command)
133     {
134         if (command.length() > 6 && command.substring(0, ID_KEYWORD.length()).equalsIgnoreCase(ID_KEYWORD))
135         {
136             Matcher matcher = PATTERN.matcher(command);
137 
138             if (matcher.matches())
139             {
140                 return true;
141             }
142             else
143             {
144                 return false;
145             }
146         }
147         return false;
148     }
149 
150     @Override
151     public boolean isPassthrough(SearchExpressionContext searchExpressionContext, String keyword)
152     {
153         return false;
154     }
155 
156     @Override
157     public boolean isLeaf(SearchExpressionContext searchExpressionContext, String keyword)
158     {
159         return false;
160     }
161 
162 }