docs: public MethodExpression getMethodExpression(FaceletContext ctx, Class type, Class[] paramTypes)
      {
          AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
          
          //volatile reads are atomic, so take the tuple to later comparison.
          Object[] localCachedExpression = cachedExpression; 
          
          if (actx.isAllowCacheELExpressions() && localCachedExpression != null &&
              (localCachedExpression.length % 3 == 0))
          {
              //If the expected type and paramTypes are the same return the cached one
              for (int i = 0; i < (localCachedExpression.length/3); i++)
              {
                  if ( ((type == null && localCachedExpression[(i*3)] == null ) ||
                       (type != null && type.equals(localCachedExpression[(i*3)])) ) &&
                       (Arrays.equals(paramTypes, (Class[]) localCachedExpression[(i*3)+1])) )
                  {
                      if ((this.capabilities & EL_CC) != 0 &&
                          localCachedExpression[(i*3)+2] instanceof LocationMethodExpression)
                      {
                          return ((LocationMethodExpression)localCachedExpression[(i*3)+2]).apply(
                                  actx.getFaceletCompositionContext().getCompositeComponentLevel());
                      }
                      return (MethodExpression) localCachedExpression[(i*3)+2];
                  }
              }
          }
          
          actx.beforeConstructELExpression();
          try
          {
              MethodExpression methodExpression = null;
              
              // From this point we can suppose this attribute contains a ELExpression
              // Now we have to check if the expression points to a composite component attribute map
              // and if so deal with it as an indirection.
              // NOTE that we have to check if the expression refers to cc.attrs for a MethodExpression
              // (#{cc.attrs.myMethod}) or only for MethodExpression parameters (#{bean.method(cc.attrs.value)}).
              if ((this.capabilities & EL_CC_ATTR_ME) != 0)
              {
                  // The MethodExpression is on parent composite component attribute map.
                  // create a pointer that are referred to the real one that is created in other side
                  // (see VDL.retargetMethodExpressions for details)
                  
                  // check for params in the the MethodExpression
                  if (ExternalSpecifications.isUnifiedELAvailable() && this.value.contains("("))
                  {
                      // if we don't throw this exception here, another ELException will be
                      // thrown later, because #{cc.attrs.method(param)} will not work as a
                      // ValueExpression pointing to a MethodExpression
                      throw new ELException("Cannot add parameters to a MethodExpression "
                              + "pointing to cc.attrs");
                  }
                  
                  ValueExpression valueExpr = this.getValueExpression(ctx, Object.class);
                  methodExpression = new ValueExpressionMethodExpression(valueExpr);
                  
                  if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
                  {
                      methodExpression = new ContextAwareTagMethodExpression(this, methodExpression);
                  }
                  else
                  {
                      methodExpression = new TagMethodExpression(this, methodExpression);
                  }
              }
              else
              {
                  ExpressionFactory f = ctx.getExpressionFactory();
                  methodExpression = f.createMethodExpression(ctx, this.value, type, paramTypes);
  
                  if (actx.getFaceletCompositionContext().isWrapTagExceptionsAsContextAware())
                  {
                      methodExpression = new ContextAwareTagMethodExpression(this, methodExpression);
                  }
                  else
                  {
                      methodExpression = new TagMethodExpression(this, methodExpression);
                  }
  
                  // if the MethodExpression contains a reference to the current composite
                  // component, the Location also has to be stored in the MethodExpression 
                  // to be able to resolve the right composite component (the one that was
                  // created from the file the Location is pointing to) later.
                  // (see MYFACES-2561 for details)
                  if ((this.capabilities & EL_CC) != 0)
                  {
                      methodExpression = new LocationMethodExpression(getLocation(), methodExpression, 
                              actx.getFaceletCompositionContext().getCompositeComponentLevel());
                  }
              }
              
                  
              if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
              {
                  if (localCachedExpression != null && (localCachedExpression.length % 3 == 0))
                  {
                      // If you use a racy single check, assign
                      // the volatile variable at the end.
                      Object[] array = new Object[localCachedExpression.length+3];
                      array[0] = type;
                      array[1] = paramTypes;
                      array[2] = methodExpression;
                      for (int i = 0; i < localCachedExpression.length; i++)
                      {
                          array[i+3] = localCachedExpression[i];
                      }
                      cachedExpression = array;
                  }
                  else
                  {
                      cachedExpression = new Object[]{type, paramTypes, methodExpression};
                  }
              }
  
              return methodExpression; 
          }
          catch (Exception e)
          {
              throw new TagAttributeException(this, e);
          }
          finally
          {
              actx.afterConstructELExpression();
          }
      }