org.ocpsoft.rewrite.config.ConfigurationLoader Maven / Gradle / Ivy
/*
* Copyright 2011 Lincoln Baxter, III
*
* 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 Lincoln Baxter, III
*/
public class ConfigurationLoader
{
public static Logger log = Logger.getLogger(ConfigurationLoader.class);
private final List> caches;
private final List> 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> priorityMap = new LinkedHashMap>();
for (ConfigurationProvider provider : providers) {
if (provider.handles(context))
{
Configuration configuration = provider.getConfiguration(context);
if (configuration != null)
{
List 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 from ConfigurationProvider ["
+ provider.getClass().getName()
+ "]");
}
}
else {
log.debug("Ignoring null Configuration from ConfigurationProvider ["
+ provider.getClass().getName()
+ "].");
}
}
}
ConfigurationBuilder result = ConfigurationBuilder.begin();
ArrayList sortedKeys = new ArrayList(priorityMap.keySet());
Collections.sort(sortedKeys);
for (Integer integer : sortedKeys) {
List 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 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 conditionVisitor = new ParameterizedConditionVisitor(callback);
new ConditionVisit(rule).accept(conditionVisitor);
Visitor 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 void addListValue(final Map> map, final K key, final T value)
{
if (!map.containsKey(key))
{
map.put(key, new ArrayList(Arrays.asList(value)));
}
else
{
map.get(key).add(value);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy