001package org.apache.commons.digester3.binder;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.LinkedHashMap;
023import java.util.Map;
024import java.util.Map.Entry;
025
026import org.apache.commons.digester3.plugins.PluginCreateRule;
027import org.apache.commons.digester3.plugins.RuleLoader;
028
029/**
030 * Builder chained when invoking {@link LinkedRuleBuilder#createPlugin()}.
031 *
032 * @since 3.0
033 */
034public final class PluginCreateRuleBuilder
035    extends AbstractBackToLinkedRuleBuilder<PluginCreateRule>
036{
037
038    private final Map<String, String> pluginClassAttributes = new LinkedHashMap<String, String>();
039
040    private final Map<String, String> pluginIdAttributes = new LinkedHashMap<String, String>();
041
042    private Class<?> baseClass;
043
044    private Class<?> dfltPluginClass;
045
046    private RuleLoader dfltPluginRuleLoader;
047
048    PluginCreateRuleBuilder( String keyPattern, String namespaceURI, RulesBinder mainBinder,
049                                    LinkedRuleBuilder mainBuilder )
050    {
051        super( keyPattern, namespaceURI, mainBinder, mainBuilder );
052    }
053
054    /**
055     * Set the class which any specified plugin <i>must</i> be descended from.
056     *
057     * @param <T> Any Java type
058     * @param type the class which any specified plugin <i>must</i> be descended from
059     * @return this builder instance
060     */
061    public <T> PluginCreateRuleBuilder ofType( Class<T> type )
062    {
063        if ( type == null )
064        {
065            reportError( "createPlugin().ofType( Class<?> )", "NULL Java type not allowed" );
066            return this;
067        }
068
069        this.baseClass = type;
070
071        return this;
072    }
073
074    /**
075     * Set the class which will be used if the user doesn't specify any plugin-class or plugin-id.
076     *
077     * @param <T> Any Java type
078     * @param type the class which will be used if the user doesn't specify any plugin-class or plugin-id.
079     * @return this builder instance
080     */
081    public <T> PluginCreateRuleBuilder usingDefaultPluginClass( /* @Nullable */Class<T> type )
082    {
083        this.dfltPluginClass = type;
084        return this;
085    }
086
087    /**
088     * Set RuleLoader instance which knows how to load the custom rules associated with the default plugin.
089     *
090     * @param <RL> Any {@link RuleLoader} extension.
091     * @param ruleLoader the RuleLoader instance which knows how to load the custom rules associated with
092     *        the default plugin.
093     * @return this builder instance
094     */
095    public <RL extends RuleLoader> PluginCreateRuleBuilder usingRuleLoader( /* @Nullable */RL ruleLoader )
096    {
097        this.dfltPluginRuleLoader = ruleLoader;
098        return this;
099    }
100
101    /**
102     * Sets the xml attribute which the input xml uses to indicate to a
103     * PluginCreateRule which class should be instantiated.
104     *
105     * @param attrName the xml attribute which the input xml uses to indicate to a
106     *                 PluginCreateRule which class should be instantiated.
107     * @return this builder instance
108     */
109    public PluginCreateRuleBuilder setPluginClassAttribute( String attrName )
110    {
111        if ( attrName == null )
112        {
113            reportError( "createPlugin().setPluginClassAttribute( String )", "NULL attribute name not allowed" );
114            return this;
115        }
116
117        return this.setPluginClassAttribute( null, attrName );
118    }
119
120    /**
121     * Sets the xml attribute which the input xml uses to indicate to a
122     * PluginCreateRule which class should be instantiated.
123     *
124     * @param namespaceUri The attribute NameSpace
125     * @param attrName The attribute name
126     * @return this builder instance
127     */
128    public PluginCreateRuleBuilder setPluginClassAttribute( /* @Nullable */String namespaceUri, String attrName )
129    {
130        if ( attrName == null )
131        {
132            reportError( "createPlugin().setPluginClassAttribute( String, String )",
133                         "NULL attribute name not allowed" );
134            return this;
135        }
136
137        return addToMap( pluginClassAttributes, namespaceUri, attrName );
138    }
139
140    /**
141     * Sets the xml attribute which the input xml uses to indicate to a 
142     * PluginCreateRule which plugin declaration is being referenced.
143     *
144     * @param attrName The attribute name
145     * @return this builder instance
146     */
147    public PluginCreateRuleBuilder setPluginIdAttribute( String attrName )
148    {
149        if ( attrName == null )
150        {
151            reportError( "createPlugin().setPluginIdAttribute( String )", "NULL attribute name not allowed" );
152            return this;
153        }
154
155        return setPluginIdAttribute( null, attrName );
156    }
157
158    /**
159     * Sets the xml attribute which the input xml uses to indicate to a 
160     * PluginCreateRule which plugin declaration is being referenced.
161     *
162     * @param namespaceUri The attribute NameSpace
163     * @param attrName The attribute name
164     * @return this builder instance
165     */
166    public PluginCreateRuleBuilder setPluginIdAttribute( /* @Nullable */String namespaceUri, String attrName )
167    {
168        if ( attrName == null )
169        {
170            reportError( "createPlugin().setPluginIdAttribute( String, String )", "NULL attribute name not allowed" );
171            return this;
172        }
173
174        return addToMap( pluginIdAttributes, namespaceUri, attrName );
175    }
176
177    /**
178     * Private internal method to set values to a {@link Map} instance and return the current builder.
179     *
180     * @param map The target {@link Map}
181     * @param namespaceUri The attribute NameSpace
182     * @param attrName The attribute name
183     * @return this builder instance
184     */
185    private PluginCreateRuleBuilder addToMap( Map<String, String> map, String namespaceUri, String attrName )
186    {
187        map.put( namespaceUri, attrName );
188        return this;
189    }
190
191    /**
192     * {@inheritDoc}
193     */
194    @Override
195    protected PluginCreateRule createRule()
196    {
197        if ( baseClass == null )
198        {
199            reportError( "createPlugin()", "'baseClass' has to be specified" );
200        }
201
202        PluginCreateRule rule;
203        if ( dfltPluginClass != null )
204        {
205            if ( dfltPluginRuleLoader != null )
206            {
207                rule = new PluginCreateRule( baseClass, dfltPluginClass, dfltPluginRuleLoader );
208            }
209            else
210            {
211                rule = new PluginCreateRule( baseClass, dfltPluginClass );
212            }
213        }
214        else
215        {
216            rule = new PluginCreateRule( baseClass );
217        }
218
219        for ( Entry<String, String> entry : pluginClassAttributes.entrySet() )
220        {
221            rule.setPluginClassAttribute( entry.getKey(), entry.getValue() );
222        }
223
224        for ( Entry<String, String> entry : pluginIdAttributes.entrySet() )
225        {
226            rule.setPluginIdAttribute( entry.getKey(), entry.getValue() );
227        }
228
229        return rule;
230    }
231
232}