001    package 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    
022    import java.util.LinkedHashMap;
023    import java.util.Map;
024    import java.util.Map.Entry;
025    
026    import org.apache.commons.digester3.plugins.PluginCreateRule;
027    import org.apache.commons.digester3.plugins.RuleLoader;
028    
029    /**
030     * Builder chained when invoking {@link LinkedRuleBuilder#createPlugin()}.
031     *
032     * @since 3.0
033     */
034    public 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    }