org.ff4j.spring.placeholder.PropertiesPlaceHolderBeanDefinitionVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.ff4j.spring.placeholder.PropertiesPlaceHolderBeanDefinitionVisitor.java

Source

package org.ff4j.spring.placeholder;

/*
 * #%L
 * ff4j-aop
 * %%
 * Copyright (C) 2013 - 2015 Ff4J
 * %%
 * 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.
 * #L%
 */

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.ff4j.FF4j;
import org.ff4j.core.Feature;
import org.ff4j.exception.FeatureNotFoundException;
import org.ff4j.exception.PropertyNotFoundException;
import org.ff4j.property.Property;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;

/**
 * Pattern Bean Visitor.
 *
 * @author <a href="mailto:cedrick.lunven@gmail.com">Cedrick LUNVEN</a>
 */
public class PropertiesPlaceHolderBeanDefinitionVisitor extends BeanDefinitionVisitor {

    /** Static commons-log LOG for this class. * */
    private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesPlaceHolderBeanDefinitionVisitor.class);

    /** Properties Map from store **/
    private Map<String, Property<?>> propertiesMap = new HashMap<String, Property<?>>();

    /** Properties Map from store **/
    private Map<String, Feature> featuresMap = new HashMap<String, Feature>();

    /** Prefix to every registry stored adress. * */
    public static final String PLACEHOLDER_PROPERTY_PREFIX = "@ff4jProperty{";

    /** Prefix to every registry stored adress. * */
    public static final String PLACEHOLDER_FEATURE_PREFIX = "@ff4jFeature{";

    /** Prefix to every registry stored adress. * */
    public static final String PLACEHOLDER_SUFFIX = "}";

    /**
     * Instanciate visitor.
     * @param serviceMap
     *      parameter service map
     */
    public PropertiesPlaceHolderBeanDefinitionVisitor(FF4j ff4j) {
        if (ff4j == null) {
            throw new IllegalArgumentException("Cannot initialize placeholding 'ff4j' is null");
        }
        this.propertiesMap = ff4j.getProperties();
        this.featuresMap = ff4j.getFeatures();
    }

    /** {@inheritDoc} */
    protected String resolveStringValue(String strVal) throws BeansException {
        return parseStringValue(strVal, propertiesMap, featuresMap, new HashSet<String>());
    }

    /**
     * Parsing value to handle
     * @param strVal
     * @param uriMap
     * @param visitedPlaceholders
     * @return
     * @throws BeanDefinitionStoreException
     */
    protected String parseStringValue(String strVal, Map<String, Property<?>> propertiesMap,
            Map<String, Feature> featureMap, Set<String> visitedPlaceholders) throws BeanDefinitionStoreException {
        StringBuilder builder = new StringBuilder(strVal);

        // @ff4jProperty{}
        int startIndex = strVal.indexOf(PLACEHOLDER_PROPERTY_PREFIX);
        while (startIndex != -1) {
            int endIndex = builder.toString().indexOf(PLACEHOLDER_SUFFIX,
                    startIndex + PLACEHOLDER_PROPERTY_PREFIX.length());
            if (endIndex != -1) {
                String placeholder = builder.substring(startIndex + PLACEHOLDER_PROPERTY_PREFIX.length(), endIndex);
                if (!visitedPlaceholders.add(placeholder)) {
                    throw new BeanDefinitionStoreException(
                            "Circular placeholder reference '" + placeholder + "' in property definitions");
                }
                if (propertiesMap == null || !propertiesMap.containsKey(placeholder)) {
                    throw new PropertyNotFoundException(
                            PLACEHOLDER_PROPERTY_PREFIX + ": Cannot perform placeholding on " + placeholder);
                }
                String propVal = propertiesMap.get(placeholder).asString();
                if (propVal != null) {
                    propVal = parseStringValue(propVal, propertiesMap, featureMap, visitedPlaceholders);
                    builder.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), propVal);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Resolved placeholder '{}' to value '{}'", placeholder, propVal);
                    }
                    startIndex = builder.toString().indexOf(PLACEHOLDER_PROPERTY_PREFIX,
                            startIndex + propVal.length());
                } else {
                    throw new BeanDefinitionStoreException("Could not resolve placeholder '" + placeholder + "'");
                }
                visitedPlaceholders.remove(placeholder);
            } else {
                startIndex = -1;
            }
        }

        // @ff4jFeature{}
        startIndex = strVal.indexOf(PLACEHOLDER_FEATURE_PREFIX);
        while (startIndex != -1) {
            int endIndex = builder.toString().indexOf(PLACEHOLDER_SUFFIX,
                    startIndex + PLACEHOLDER_FEATURE_PREFIX.length());
            if (endIndex != -1) {
                String placeholder = builder.substring(startIndex + PLACEHOLDER_FEATURE_PREFIX.length(), endIndex);
                if (!visitedPlaceholders.add(placeholder)) {
                    throw new BeanDefinitionStoreException(
                            "Circular placeholder reference '" + placeholder + "' in property definitions");
                }
                if (featureMap == null || !featureMap.containsKey(placeholder)) {
                    throw new FeatureNotFoundException(
                            PLACEHOLDER_FEATURE_PREFIX + ": Cannot perform placeholding on " + placeholder);
                }
                String propVal = String.valueOf(featureMap.get(placeholder).isEnable());
                if (propVal != null) {
                    propVal = parseStringValue(propVal, propertiesMap, featureMap, visitedPlaceholders);
                    builder.replace(startIndex, endIndex + PLACEHOLDER_FEATURE_PREFIX.length(), propVal);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Resolved placeholder '{}' to value '{}'", placeholder, propVal);
                    }
                    startIndex = builder.toString().indexOf(PLACEHOLDER_FEATURE_PREFIX,
                            startIndex + propVal.length());
                } else {
                    throw new BeanDefinitionStoreException("Could not resolve placeholder '" + placeholder + "'");
                }
                visitedPlaceholders.remove(placeholder);
            } else {
                startIndex = -1;
            }
        }

        return builder.toString();
    }

}