All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.digester.annotations.FromAnnotationsRuleSet Maven / Gradle / Ivy

The newest version!
/* $Id: FromAnnotationsRuleSet.java 992746 2010-09-05 09:31:53Z simonetripodi $
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.digester.annotations;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.RuleSet;

/**
 * A {@link RuleSet} implementation that's able to inject {@link Rule}s created
 * with the annotations analysis.
 *
 * @since 2.1
 */
public final class FromAnnotationsRuleSet implements RuleSet {

    /**
     * The data structure that stores the patterns/{@link AnnotationRuleProvider}
     * pairs.
     */
    private final Map>> rules =
        new LinkedHashMap>>();

    /**
     * Maintains all the classes that this RuleSet produces mapping for.
     */
    private final Set> mappedClasses = new HashSet>();

    private final DigesterLoader digesterLoader;

    /**
     * The namespace URI.
     */
    private volatile String namespaceURI;

    /**
     * Created a new {@code FromAnnotationsRuleSet} instance.
     *
     * @param digesterLoader the parent DigesterLoader.
     */
    protected FromAnnotationsRuleSet(DigesterLoader digesterLoader) {
        this.digesterLoader = digesterLoader;
    }

    /**
     * {@inheritDoc}
     */
    public void addRuleInstances(Digester digester) {
        String pattern;
        Rule rule;
        for (Entry>> entry :
                this.rules.entrySet()) {
            pattern = entry.getKey();
            for (AnnotationRuleProvider provider : entry.getValue()) {
                rule = provider.get();
                if (this.namespaceURI != null) {
                    rule.setNamespaceURI(this.namespaceURI);
                }
                digester.addRule(pattern, rule);
            }
        }
    }

    /**
     * Analyzes the target class and adds the {@link AnnotationRuleProvider}s to
     * this {@link FromAnnotationsRuleSet}.
     *
     * @param target the class has to be analyzed.
     */
    public void addRules(Class target) {
        this.digesterLoader.addRulesTo(target, this);
    }

    /**
     * Builds and register an {@link AnnotationRuleProvider} for a specific
     * pattern.
     *
     * @param  the {@link AnnotationRuleProvider} type.
     * @param pattern the pattern has to be associated to the rule provider.
     * @param klass the {@link AnnotationRuleProvider} type has to be instantiated.
     * @param annotation the current visited annotation.
     * @param element the current visited element.
     */
    public >
        void addRuleProvider(String pattern,
            Class klass,
            A annotation,
            E element) {

        T annotationRuleProvider =
            this.digesterLoader.getAnnotationRuleProviderFactory().newInstance(klass);
        annotationRuleProvider.init(annotation, element);
        this.addRuleProvider(pattern, annotationRuleProvider);
    }

    /**
     * Register an {@link AnnotationRuleProvider} for a specific pattern.
     *
     * @param pattern the pattern has to be associated to the rule provider.
     * @param ruleProvider the provider that builds the digester rule.
     */
    @SuppressWarnings("unchecked")
    public void addRuleProvider(String pattern,
            AnnotationRuleProvider ruleProvider) {
        List> rules;

        if (this.rules.containsKey(pattern)) {
            rules = this.rules.get(pattern);
        } else {
            rules = new ArrayList>();
            this.rules.put(pattern, rules);
        }

        rules.add((AnnotationRuleProvider) ruleProvider);
    }

    /**
     * Retrieves a specific instance of the {@link AnnotationRuleProvider} for
     * the input pattern.
     *
     * @param  the {@link AnnotationRuleProvider} type
     * @param pattern the input pattern
     * @param providerClass the {@link AnnotationRuleProvider} class
     * @return an {@link AnnotationRuleProvider} for the input pattern if found,
     *         null otherwise.
     */
    public >
            T getProvider(String pattern, Class providerClass) {

        if (!this.rules.containsKey(pattern)) {
            return null;
        }

        for (AnnotationRuleProvider rule : this.rules.get(pattern)) {
            if (providerClass.isInstance(rule)) {
                return providerClass.cast(rule);
            }
        }

        return null;
    }

    /**
     * Add created {@link AnnotationRuleProvider}s created in another analysis
     * session.
     *
     * @param ruleSet the {@code RuleSet} created in another analysis session.
     */
    public void addRulesProviderFrom(final FromAnnotationsRuleSet ruleSet) {
        this.rules.putAll(ruleSet.getRules());
    }

    /**
     * Checks if this RuleSet builds Digester mapping rules for the input type.
     *
     * @param clazz the input type.
     * @return true, if this RuleSet builds Digester mapping rules for the input
     *         type, false otherwise.
     */
    protected boolean mapsClass(Class clazz) {
        return this.mappedClasses.contains(clazz);
    }

    /**
     * Remember that this RuleSet is able to build Digester mapping rules for
     * the input type.
     *
     * @param clazz the input type.
     */
    protected void addMappedClass(Class clazz) {
        this.mappedClasses.add(clazz);
    }

    /**
     * Returns the data structure  the patterns/{@link AnnotationRuleProvider}
     * pairs.
     *
     * @return the data structure  the patterns/{@link AnnotationRuleProvider}
     *         pairs.
     */
    private Map>> getRules() {
        return this.rules;
    }

    /**
     * {@inheritDoc}
     */
    public String getNamespaceURI() {
        return this.namespaceURI;
    }

    /**
     * Sets the namespace URI that will be applied to all Rule instances
     * created from this RuleSet.
     *
     * @param namespaceURI the namespace URI that will be applied to all Rule
     * instances created from this RuleSet.
     */
    public void setNamespaceURI(String namespaceURI) {
        this.namespaceURI = namespaceURI;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "{ mappedClasses="
            + this.mappedClasses
            + ", rules="
            + this.rules.toString()
            + ", namespaceURI="
            + this.namespaceURI
            + " }";
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy