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 static java.lang.String.format;
023    
024    import org.apache.commons.digester3.AbstractMethodRule;
025    
026    /**
027     * Builder chained when invoking {@link LinkedRuleBuilder#setNext(String)},
028     * {@link LinkedRuleBuilder#setRoot(String)} or {@link LinkedRuleBuilder#setTop(String)}.
029     *
030     * @param <R> any {@link AbstractMethodRule} concrete implementation, typically
031     *        {@link org.apache.commons.digester3.SetNextRule}, {@link org.apache.commons.digester3.SetRootRule}
032     *        and {@link org.apache.commons.digester3.SetTopRule}
033     * @since 3.0
034     */
035    public abstract class AbstractParamTypeBuilder<R extends AbstractMethodRule>
036        extends AbstractBackToLinkedRuleBuilder<R>
037    {
038    
039        private final String methodName;
040    
041        private final ClassLoader classLoader;
042    
043        private boolean useExactMatch = false;
044    
045        private Class<?> paramType;
046    
047        private boolean fireOnBegin = false;
048    
049        AbstractParamTypeBuilder( String keyPattern, String namespaceURI, RulesBinder mainBinder,
050                                  LinkedRuleBuilder mainBuilder, String methodName, ClassLoader classLoader )
051        {
052            super( keyPattern, namespaceURI, mainBinder, mainBuilder );
053            this.methodName = methodName;
054            this.classLoader = classLoader;
055        }
056    
057        /**
058         * Sets the Java class of the method's argument.
059         * 
060         * If you wish to use a primitive type, specify the corresonding
061         * Java wrapper class instead, such as {@code java.lang.Boolean}
062         * for a {@code boolean} parameter.
063         *
064         * @param paramType The Java class of the method's argument
065         * @return this builder instance
066         */
067        public final AbstractParamTypeBuilder<R> withParameterType( Class<?> paramType )
068        {
069            if ( paramType == null )
070            {
071                reportError( format( ".%s.withParameterType( Class<?> )", methodName ), "NULL Java type not allowed" );
072                return this;
073            }
074            this.paramType = paramType;
075            return withParameterType( paramType.getName() );
076        }
077    
078        /**
079         * Sets the Java class name of the method's argument.
080         * 
081         * If you wish to use a primitive type, specify the corresonding
082         * Java wrapper class instead, such as {@code java.lang.Boolean}
083         * for a {@code boolean} parameter.
084         *
085         * @param paramType The Java class name of the method's argument
086         * @return this builder instance
087         */
088        public final AbstractParamTypeBuilder<R> withParameterType( String paramType )
089        {
090            if ( paramType == null )
091            {
092                reportError( format( ".%s.withParameterType( Class<?> )", methodName ), "NULL Java type not allowed" );
093                return this;
094            }
095    
096            if ( this.paramType == null )
097            {
098                try
099                {
100                    this.paramType = classLoader.loadClass( paramType );
101                }
102                catch ( ClassNotFoundException e )
103                {
104                    this.reportError( format( ".%s.withParameterType( Class<?> )", methodName ),
105                                      format( "class '%s' cannot be load", paramType ) );
106                }
107            }
108            return this;
109        }
110    
111        /**
112         * Sets exact matching being used.
113         *
114         * @param useExactMatch The exact matching being used
115         * @return this builder instance
116         */
117        public final AbstractParamTypeBuilder<R> useExactMatch( boolean useExactMatch )
118        {
119            this.useExactMatch = useExactMatch;
120            return this;
121        }
122    
123        /**
124         * Marks the rule be invoked when {@code begin} or {@code end} events match.
125         *
126         * @param fireOnBegin true, to invoke the rule at {@code begin}, false for {@code end}
127         * @return this builder instance
128         */
129        public final AbstractParamTypeBuilder<R> fireOnBegin( boolean fireOnBegin )
130        {
131            this.fireOnBegin = fireOnBegin;
132            return this;
133        }
134    
135        final String getMethodName()
136        {
137            return methodName;
138        }
139    
140        final Class<?> getParamType()
141        {
142            return paramType;
143        }
144    
145        final boolean isUseExactMatch()
146        {
147            return useExactMatch;
148        }
149    
150        final boolean isFireOnBegin()
151        {
152            return fireOnBegin;
153        }
154    
155    }