001    package org.apache.commons.betwixt.digester;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     * 
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     * 
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */ 
019    
020    import java.beans.PropertyDescriptor;
021    import java.lang.reflect.Method;
022    
023    import org.apache.commons.betwixt.ElementDescriptor;
024    import org.apache.commons.betwixt.TextDescriptor;
025    import org.apache.commons.betwixt.XMLBeanInfo;
026    import org.apache.commons.betwixt.expression.ConstantExpression;
027    import org.apache.commons.betwixt.expression.MethodExpression;
028    import org.apache.commons.betwixt.expression.MethodUpdater;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.xml.sax.Attributes;
032    import org.xml.sax.SAXException;
033    
034    /** 
035      * <p>Rule for parsing &lt;text&gt; elements.
036      * These allow mixed content text to be specified.
037      * A mixed content element example:
038      * <pre>
039      *     &lt;foo&gt;text&lt;bar/&gt;&lt;/foo&gt;
040      * </pre>
041      * </p>
042      *
043      * @author Robert Burrell Donkin
044      * @version $Id: TextRule.java 438373 2006-08-30 05:17:21Z bayard $
045      */
046    public class TextRule extends MappedPropertyRule {
047    
048        /** Logger */
049        private static final Log log = LogFactory.getLog( TextRule.class );
050        /** Base constructor */
051        public TextRule() {}
052        
053        // Rule interface
054        //-------------------------------------------------------------------------    
055        
056        /**
057         * Process the beginning of this element.
058         *
059         * @param attributes The attribute list of this element
060         * @throws SAXException 1. If this tag's parent is not an element tag.
061         * 2. If this tag has a value attribute together with either a property
062         * or type attribute.
063         */
064        public void begin(String name, String namespace, Attributes attributes) throws SAXException {
065            
066            TextDescriptor descriptor = new TextDescriptor();
067            
068            String value = attributes.getValue( "value" );
069            String propertyName = attributes.getValue( "property" );
070            String propertyType = attributes.getValue( "type" );
071            
072            if ( value != null) {
073                if ( propertyName != null || propertyType != null ) {
074                    // not allowed
075                    throw new SAXException(
076                        "You cannot specify attribute 'value' together with either " 
077                        + " the 'property' or 'type' attributes");                
078                }
079                // fixed value text
080                descriptor.setTextExpression( new ConstantExpression( value ) );
081                
082            } else {
083                // property based text
084                descriptor.setPropertyName( propertyName );
085                
086                Class beanClass = getBeanClass();
087                
088                // set the property type using reflection
089                descriptor.setPropertyType( 
090                    getPropertyType( propertyType, beanClass, propertyName ) 
091                );
092                
093                if ( beanClass != null ) {
094                    String descriptorPropertyName = descriptor.getPropertyName();
095                    PropertyDescriptor propertyDescriptor = 
096                        getPropertyDescriptor( beanClass, descriptorPropertyName );
097                    if ( propertyDescriptor != null ) { 
098                            Method readMethod = propertyDescriptor.getReadMethod();
099                            descriptor.setTextExpression( new MethodExpression( readMethod ) );
100                            Method writeMethod = propertyDescriptor.getWriteMethod();
101                            if (writeMethod != null) {
102                                descriptor.setUpdater( new MethodUpdater(writeMethod));
103                            }
104                            getProcessedPropertyNameSet().add( descriptorPropertyName );
105                    }
106                }
107            }
108            
109            Object top = digester.peek();
110            if ( top instanceof XMLBeanInfo ) {
111                XMLBeanInfo beanInfo = (XMLBeanInfo) top;
112                ElementDescriptor elementDescriptor = beanInfo.getElementDescriptor();
113                if (elementDescriptor != null) {
114                    elementDescriptor.addContentDescriptor( descriptor );
115                }
116                
117            } else if ( top instanceof ElementDescriptor ) {
118                ElementDescriptor parent = (ElementDescriptor) top;
119                parent.addContentDescriptor( descriptor );
120                
121            } else {
122                throw new SAXException( "Invalid use of <text>. It should " 
123                    + "be nested <text> nodes" );
124            }
125        }
126    }