Package org.ocpsoft.rewrite.config

Source Code of org.ocpsoft.rewrite.config.ConfigurationLoader

/*
* Copyright 2011 <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.config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.Evaluation;
import org.ocpsoft.rewrite.context.Context;
import org.ocpsoft.rewrite.param.ConfigurableParameter;
import org.ocpsoft.rewrite.param.DefaultParameter;
import org.ocpsoft.rewrite.param.Parameter;
import org.ocpsoft.rewrite.param.ParameterStore;
import org.ocpsoft.rewrite.param.Parameterized;
import org.ocpsoft.rewrite.param.ParameterizedRule;
import org.ocpsoft.rewrite.spi.ConfigurationCacheProvider;
import org.ocpsoft.rewrite.util.Visitor;

/**
* Responsible for loading all {@link ConfigurationProvider} instances, and building a single unified
* {@link Configuration} based on {@link ConfigurationProvider#priority()}
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class ConfigurationLoader
{
   public static Logger log = Logger.getLogger(ConfigurationLoader.class);
   private final List<ConfigurationCacheProvider<?>> caches;
   private final List<ConfigurationProvider<?>> providers;

   @SuppressWarnings({ "unchecked" })
   public ConfigurationLoader(Object context)
   {
      caches = Iterators.asList(ServiceLoader.load(ConfigurationCacheProvider.class));
      Collections.sort(caches, new WeightedComparator());

      providers = Iterators.asList(ServiceLoader.load(ConfigurationProvider.class));
      Collections.sort(providers, new WeightedComparator());
   }

   /**
    * Get a new {@link ConfigurationLoader} instance.
    */
   public static ConfigurationLoader create(final Object context)
   {
      return new ConfigurationLoader(context);
   }

   /**
    * Load all {@link ConfigurationProvider} instances, sort by {@link ConfigurationProvider#priority()}, and return a
    * unified, composite {@link Configuration} object.
    */
   public Configuration loadConfiguration(Object context)
   {
      if (caches.isEmpty())
      {
         return build(context);
      }
      return buildCached(context);
   }

   @SuppressWarnings({ "rawtypes", "unchecked" })
   private Configuration buildCached(Object context)
   {
      Configuration result = null;
      /*
       * Do not force synchronization if a configuration is primed.
       */
      for (ConfigurationCacheProvider cache : caches) {
         Configuration cachedConfig = cache.getConfiguration(context);
         if (cachedConfig != null)
         {
            result = cachedConfig;
            break;
         }
      }

      if (result == null)
      {
         synchronized (this) {

            /*
             * Double check in order to ensure that a configuration wasn't built after our first cache check.
             */
            for (ConfigurationCacheProvider cache : caches) {
               Configuration cachedConfig = cache.getConfiguration(context);
               if (cachedConfig != null)
               {
                  result = cachedConfig;
                  break;
               }
            }

            if (result == null)
            {
               result = build(context);

               for (ConfigurationCacheProvider cache : caches) {
                  cache.setConfiguration(context, result);
               }
            }
         }
      }

      return result;
   }

   @SuppressWarnings({ "rawtypes", "unchecked" })
   private Configuration build(Object context)
   {

      Map<Integer, List<Rule>> priorityMap = new LinkedHashMap<Integer, List<Rule>>();
      for (ConfigurationProvider provider : providers) {
         if (provider.handles(context))
         {
            Configuration configuration = provider.getConfiguration(context);

            if (configuration != null)
            {
               List<Rule> rules = configuration.getRules();
               if (rules != null)
               {
                  for (Rule rule : rules) {
                     if (rule != null)
                     {
                        if (rule instanceof RelocatableRule && ((RelocatableRule) rule).isRelocated())
                           addListValue(priorityMap, ((RelocatableRule) rule).priority(), rule);
                        else
                           addListValue(priorityMap, provider.priority(), rule);
                     }
                     else {
                        log.debug("Ignoring null Rule from ConfigurationProvider ["
                                 + provider.getClass().getName()
                                 + "]");
                     }
                  }
               }
               else {
                  log.debug("Ignoring null List<Rule> from ConfigurationProvider ["
                           + provider.getClass().getName()
                           + "]");
               }
            }
            else {
               log.debug("Ignoring null Configuration from ConfigurationProvider ["
                        + provider.getClass().getName()
                        + "].");
            }
         }
      }

      ConfigurationBuilder result = ConfigurationBuilder.begin();
      ArrayList<Integer> sortedKeys = new ArrayList<Integer>(priorityMap.keySet());
      Collections.sort(sortedKeys);

      for (Integer integer : sortedKeys) {
         List<Rule> list = priorityMap.get(integer);
         for (final Rule rule : list) {
            result.addRule(rule);

            try {
               if (rule instanceof ParameterizedRule) {
                  ParameterizedCallback callback = new ParameterizedCallback() {
                     @Override
                     public void call(Parameterized parameterized)
                     {
                        Set<String> names = parameterized.getRequiredParameterNames();
                        ParameterStore store = ((ParameterizedRule) rule).getParameterStore();

                        if (names != null)
                           for (String name : names) {
                              Parameter<?> parameter = store.get(name, new DefaultParameter(name));
                              if (parameter instanceof ConfigurableParameter<?>)
                                 ((ConfigurableParameter<?>) parameter).bindsTo(Evaluation.property(name));
                           }

                        parameterized.setParameterStore(store);
                     }
                  };

                  Visitor<Condition> conditionVisitor = new ParameterizedConditionVisitor(callback);
                  new ConditionVisit(rule).accept(conditionVisitor);

                  Visitor<Operation> operationVisitor = new ParameterizedOperationVisitor(callback);
                  new OperationVisit(rule).accept(operationVisitor);
               }
            }
            catch (RuntimeException e) {
               String message = "Error encountered while visiting rule: " + rule;

               if (rule instanceof Context)
               {
                  message += " defined at " + ((Context) rule).get(RuleMetadata.PROVIDER_LOCATION) + "\n";
               }
               log.error(message);
               throw e;
            }
         }
      }

      return result;
   }

   @SuppressWarnings("unchecked")
   public static <K, T> void addListValue(final Map<K, List<T>> map, final K key, final T value)
   {
      if (!map.containsKey(key))
      {
         map.put(key, new ArrayList<T>(Arrays.asList(value)));
      }
      else
      {
         map.get(key).add(value);
      }
   }

}
TOP

Related Classes of org.ocpsoft.rewrite.config.ConfigurationLoader

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.