001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */ 
017    package org.apache.commons.betwixt.io.read;
018    
019    import java.util.ArrayList;
020    import java.util.Iterator;
021    
022    /**  
023      * <p>Chain implementation that's backed by a list.
024      * This is the default implementation used by Betwixt.
025      * </p><p>
026      * <strong>Note</strong> this implementation is <em>not</em>
027      * intended to allow multiple threads of execution to perform
028      * modification operations concurrently with traversal of the chain.
029      * Users who require this behaviour are advised to create their own implementation.
030      * </p>
031      *
032      * @author Robert Burrell Donkin
033      * @since 0.5
034      */
035    public class BeanCreationList extends BeanCreationChain {
036        
037    //-------------------------------------------------------- Class Methods
038    
039        /** 
040         * Creates the default <code>BeanCreationChain</code> used when reading beans.
041         * @return a <code>BeanCreationList</code> with the default creators loader in order, not null
042         */
043        public static final BeanCreationList createStandardChain() {
044            BeanCreationList chain = new BeanCreationList();
045            chain.addBeanCreator( ChainedBeanCreatorFactory.createIDREFBeanCreator() );
046            chain.addBeanCreator( ChainedBeanCreatorFactory.createDerivedBeanCreator() );
047            chain.addBeanCreator( ChainedBeanCreatorFactory.createElementTypeBeanCreator() );
048            return chain;
049        }
050        
051    
052        
053    //-------------------------------------------------------- Attributes
054        /** The list backing this chain */
055        private ArrayList beanCreators = new ArrayList();
056        
057    //-------------------------------------------------------- Methods
058        
059        /**
060          * Creates an Object based on the given element mapping and read context.
061          * Delegates to chain.
062          *
063          * @param elementMapping the element mapping details
064          * @param readContext create against this context 
065          * @return the created bean, possibly null
066          */
067        public Object create( ElementMapping elementMapping, ReadContext readContext ) {
068            ChainWorker worker = new ChainWorker();
069            return worker.create( elementMapping, readContext );
070        }
071        
072    //-------------------------------------------------------- Properties
073        
074        /**
075          * Gets the number of BeanCreators in the wrapped chain.
076          * @return the number of <code>ChainedBeanCreator</code>'s in the current chain
077          */
078        public int getSize() {
079            return beanCreators.size();
080        }
081        
082        /**
083          * Inserts a <code>BeanCreator</code> at the given position in the chain.
084          * Shifts the object currently in that position - and any subsequent elements -
085          * to the right.
086          *
087          * @param index index at which the creator should be inserted
088          * @param beanCreator the <code>BeanCreator</code> to be inserted, not null
089          * @throws IndexOutOfBoundsException if the index is out of the range 
090          * <code>(index < 0 || index > getSize())
091          */
092        public void insertBeanCreator(
093                                    int index, 
094                                    ChainedBeanCreator beanCreator ) 
095                                        throws IndexOutOfBoundsException {
096            beanCreators.add( index, beanCreator );
097        }
098        
099        /**
100          * Adds a <code>BeanCreator</code> to the end of the chain.
101          * @param beanCreator the <code>BeanCreator</code> to be inserted, not null
102          */
103        public void addBeanCreator( ChainedBeanCreator beanCreator ) {
104            beanCreators.add( beanCreator );
105        }
106        
107        /** 
108          * Clears the creator chain.
109          */
110        public void clearBeanCreators() {
111            beanCreators.clear();
112        }
113         
114        /** Worker class walks a chain */
115        private class ChainWorker extends BeanCreationChain {
116            /** Iterator for the creator list */
117            private Iterator iterator;
118            /** Creates the iterator */
119            ChainWorker() {
120                iterator = beanCreators.iterator();
121            }
122        
123            /**
124              * @see BeanCreationChain#create
125              */
126            public Object create( ElementMapping elementMapping, ReadContext readContext ) {
127                if ( iterator.hasNext() ) {
128                    ChainedBeanCreator beanCreator = (ChainedBeanCreator) iterator.next();
129                    return beanCreator.create( elementMapping, readContext, this );
130                }
131                
132                return null;
133            }
134        }
135    }