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 static java.lang.String.format;
023
024import 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 */
035public 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}