Package org.ocpsoft.rewrite.el

Source Code of org.ocpsoft.rewrite.el.El$ElProperties

/*
* Copyright 2013 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
* Licensed 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.ocpsoft.rewrite.el;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.ocpsoft.common.pattern.WeightedComparator;
import org.ocpsoft.common.services.ServiceLoader;
import org.ocpsoft.common.util.Iterators;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.rewrite.bind.Binding;
import org.ocpsoft.rewrite.bind.Retrieval;
import org.ocpsoft.rewrite.context.EvaluationContext;
import org.ocpsoft.rewrite.el.spi.ExpressionLanguageProvider;
import org.ocpsoft.rewrite.event.Rewrite;
import org.ocpsoft.rewrite.exception.RewriteException;

/**
* Responsible for binding to EL expressions.
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public abstract class El implements Binding, Retrieval
{
   private static final Logger log = Logger.getLogger(El.class);
   private static volatile List<ExpressionLanguageProvider> _providers;

   /**
    * Create a new EL Method binding using distinct expressions to submit and retrieve values. The method intended for
    * use in submission must accept a single parameter of the expected type.
    */
   public static El method(final String retrieve, final String submit)
   {
      return new ElMethod(new ConstantExpression(retrieve), new ConstantExpression(submit));
   }

   /**
    * Create a new EL Method binding to retrieve values. The method must return a value of the expected type.
    */
   public static El retrievalMethod(final String expression)
   {
      return new ElMethod(new ConstantExpression(expression), null);
   }

   /**
    * Create a new EL Method binding to retrieve values. This method allows the caller to supply {@link Method} instance
    * to refer to the method that should be invoked.
    */
   public static El retrievalMethod(final Method method)
   {
      return retrievalMethod(method.getDeclaringClass(), method.getName());
   }

   /**
    * Create a new EL Method binding to retrieve values. This method allows the caller to supply the {@link Class}
    * representing the type of the target object and the method name to refer to the method that should be invoked.
    */
   public static El retrievalMethod(final Class<?> clazz, final String methodName)
   {
      return new ElMethod(new TypeBasedExpression(clazz, methodName), null);
   }

   /**
    * Create a new EL Method binding to submit values. The method must accept a single parameter of the expected type.
    */
   public static El submissionMethod(final String expression)
   {
      return new ElMethod(null, new ConstantExpression(expression));
   }

   /**
    * Create a new EL Value binding using a single expression to submit and retrieve values. The specified property must
    * either be public, or have a publicly defined getter/setter.
    */
   public static El property(final String expression)
   {
      return new ElProperty(new ConstantExpression(expression));
   }

   /**
    * Create a new EL Value binding using a single expression to submit and retrieve values. The specified property must
    * either be public, or have a publicly defined getter/setter. Instead of an EL expression this method expects a
    * {@link Field} argument. The EL expression will be automatically created at runtime.
    */
   public static El property(final Field field)
   {
      return property(field.getDeclaringClass(), field.getName());
   }

   /**
    * Create a new EL Value binding using a single expression to submit and retrieve values. The specified property must
    * either be public, or have a publicly defined getter/setter. Instead of an EL expression this method expects the
    * {@link Class} representing the type of the target object and the field name. The EL expression will be
    * automatically created at runtime.
    */
   public static El property(final Class<?> clazz, final String fieldName)
   {
      return new ElProperty(new TypeBasedExpression(clazz, fieldName));
   }

   /**
    * Create a new EL Value binding using a single expression to submit and retrieve values. The specified property must
    * either be public, or have a publicly defined getter/setter.
    */
   public static El properties(final String submit, final String retrieve)
   {
      return new ElProperties(new ConstantExpression(submit),
               new ConstantExpression(retrieve));
   }

   /**
    * Create a new EL Value binding using a single expression to submit and retrieve values. The specified property must
    * either be public, or have a publicly defined getter/setter. Instead of an EL expression this method expects a
    * {@link Field} argument. The EL expression will be automatically created at runtime.
    */
   public static El properties(final Field submit, final Field retrieve)
   {
      return new ElProperties(new TypeBasedExpression(submit.getDeclaringClass(), submit.getName()),
               new TypeBasedExpression(retrieve.getDeclaringClass(), retrieve.getName()));
   }

   @SuppressWarnings("unchecked")
   private static List<ExpressionLanguageProvider> getProviders()
   {
      if (_providers == null)
      {
         synchronized (El.class)
         {
            if (_providers == null)
            {
               _providers = Iterators.asList(ServiceLoader.load(ExpressionLanguageProvider.class));
               Collections.sort(_providers, new WeightedComparator());

               if (_providers.isEmpty())
               {
                  log.warn("No instances of [{}] were configured. EL support is disabled.",
                           ExpressionLanguageProvider.class.getName());
               }

            }

         }
      }
      return _providers;
   }

   private static Object executeProviderCallable(Rewrite event, EvaluationContext context,
            ProviderCallable<Object> providerCallable)
   {
      List<Exception> exceptions = new ArrayList<Exception>();
      for (ExpressionLanguageProvider provider : getProviders()) {
         try
         {
            return providerCallable.call(event, context, provider);
         }
         catch (RuntimeException e) {
            throw e;
         }
         catch (Exception e)
         {
            exceptions.add(e);
         }
      }

      for (Exception exception : exceptions) {
         log.error("DEFERRED EXCEPTION", exception);
      }
      throw new RewriteException("No registered " + ExpressionLanguageProvider.class.getName()
               + " could handle the Expression [" + providerCallable.getExpression() + "]");
   }

   /**
    * Handle EL Method Invocation and Value Extraction
    */
   public static class ElMethod extends El
   {
      private final Expression getExpression;
      private final Expression setExpression;

      public ElMethod(final Expression getExpression, final Expression setExpression)
      {
         this.getExpression = getExpression;
         this.setExpression = setExpression;
      }

      @Override
      public Object retrieve(final Rewrite event, final EvaluationContext context)
      {
         if (!supportsRetrieval())
            throw new RewriteException("Method binding expression supports submission only [" + setExpression
                     + "], no value retrieval expression was defined");

         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               return provider.evaluateMethodExpression(getExpression.getExpression());
            }

            @Override
            public String getExpression()
            {
               return ElMethod.this.getExpression.getExpression();
            }
         });
      }

      @Override
      public Object submit(final Rewrite event, final EvaluationContext context, final Object value)
      {
         if (!supportsSubmission())
            throw new RewriteException("Method binding expression supports retrieval only [" + getExpression
                     + "], no value submission expression was defined");

         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               return provider.evaluateMethodExpression(setExpression.getExpression(), value);
            }

            @Override
            public String getExpression()
            {
               return ElMethod.this.setExpression.getExpression();
            }
         });
      }

      @Override
      public boolean supportsRetrieval()
      {
         return getExpression != null;
      }

      @Override
      public boolean supportsSubmission()
      {
         return setExpression != null;
      }

      @Override
      public String toString()
      {
         return "ElMethod [retrieve= [ " + getExpression + " }, submit= [ " + setExpression + " ]";
      }

   }

   /**
    * Handle EL Property Injection and Extraction
    */
   public static class ElProperty extends El
   {
      private final Expression expression;

      public ElProperty(final Expression expression)
      {
         this.expression = expression;
      }

      @Override
      public Object retrieve(final Rewrite event, final EvaluationContext context)
      {
         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               return provider.retrieveValue(expression.getExpression());
            }

            @Override
            public String getExpression()
            {
               return ElProperty.this.expression.getExpression();
            }
         });
      }

      @Override
      public Object submit(final Rewrite event, final EvaluationContext context, final Object value)
      {
         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               provider.submitValue(expression.getExpression(), value);
               return null;
            }

            @Override
            public String getExpression()
            {
               return ElProperty.this.expression.getExpression();
            }
         });
      }

      @Override
      public boolean supportsRetrieval()
      {
         return true;
      }

      @Override
      public boolean supportsSubmission()
      {
         return true;
      }

      @Override
      public String toString()
      {
         return "ElProperty [ " + expression + " ]";
      }

   }

   public static class ElProperties extends El
   {

      private Expression submit;
      private Expression retrieve;

      public ElProperties(final Expression submit, final Expression retrieve)
      {
         this.submit = submit;
         this.retrieve = retrieve;
      }

      @Override
      public Object retrieve(final Rewrite event, final EvaluationContext context)
      {
         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               return provider.retrieveValue(retrieve.getExpression());
            }

            @Override
            public String getExpression()
            {
               return retrieve.getExpression();
            }
         });
      }

      @Override
      public Object submit(final Rewrite event, final EvaluationContext context, final Object value)
      {
         return executeProviderCallable(event, context, new ProviderCallable<Object>() {
            @Override
            public Object call(Rewrite event, EvaluationContext context, ExpressionLanguageProvider provider)
                     throws Exception
            {
               provider.submitValue(submit.getExpression(), value);
               return null;
            }

            @Override
            public String getExpression()
            {
               return submit.getExpression();
            }
         });
      }

      @Override
      public boolean supportsRetrieval()
      {
         return true;
      }

      @Override
      public boolean supportsSubmission()
      {
         return true;
      }

      @Override
      public String toString()
      {
         return "ElProperties [ submitTo =>" + submit + ", retrieveFrom=>" + retrieve + " ]";
      }

   }
}
TOP

Related Classes of org.ocpsoft.rewrite.el.El$ElProperties

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.