Coverage Report - org.apache.commons.betwixt.io.read.ArrayBindAction

Classes in this File Line Coverage Branch Coverage Complexity
ArrayBindAction
97% 
100% 
1.167

 1  
 /*
 2  
  * Copyright 2004 The Apache Software Foundation.
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
  
 17  
 package org.apache.commons.betwixt.io.read;
 18  
 
 19  
 import java.util.ArrayList;
 20  
 import java.util.List;
 21  
 
 22  
 import org.apache.commons.betwixt.ElementDescriptor;
 23  
 import org.apache.commons.betwixt.expression.Context;
 24  
 import org.apache.commons.betwixt.expression.Updater;
 25  
 import org.xml.sax.Attributes;
 26  
 
 27  
 /**
 28  
  * <p>Acts to bind an array property.
 29  
  * Note that this is intended to be used to map 
 30  
  * properties with a setter taking an array 
 31  
  * but which do not have an adder.</p>
 32  
  * <p>
 33  
  * <strong>Note</strong> this implementation has state 
 34  
  * and therefore cannot be used concurrently (in simultaneous readings).
 35  
  * </p>
 36  
  * @author <a href='http://jakarta.apache.org/'>Apache Commons Team</a>
 37  
  * @version $Revision: 155402 $
 38  
  */
 39  286
 public class ArrayBindAction extends MappingAction.Base {
 40  
    
 41  
     
 42  
     /**
 43  
      * Factory method creates implementations to map arrays.
 44  
      * @param elementDescriptor <code>ElementDescriptor</code> to be mapped, 
 45  
      * not null
 46  
      * @return <code>MappingAction</code>, not null 
 47  
      */
 48  
     public static final MappingAction createMappingAction(ElementDescriptor elementDescriptor) {
 49  143
         MappingAction result = new ArrayBindAction();
 50  143
         if (elementDescriptor.getSingularPropertyType() != null && 
 51  143
                 !elementDescriptor.getSingularPropertyType().isArray()) {
 52  104
             result = BeanBindAction.INSTANCE;
 53  
         }
 54  143
         return result;
 55  
     }
 56  
     
 57  143
     private BeanMapping beanMapping = new BeanMapping();
 58  
     private Updater originalUpdater;
 59  
     
 60  
     /**
 61  
      * Mapping arrays requires the addition of a temporary object
 62  
      * (an <code>ArrayList</code>) into the stack together with an
 63  
      * updater for that object.   
 64  
      *    
 65  
      */
 66  
     public MappingAction begin(
 67  
         String namespace,
 68  
         String name,
 69  
         Attributes attributes,
 70  
         ReadContext context)
 71  
         throws Exception {
 72  
         // push an array onto the object stack
 73  26
         context.pushBean(new ArrayList());
 74  26
         return this;
 75  
     }
 76  
 
 77  
     /**
 78  
      * Pops the <code>ArrayList</code> and the updater from
 79  
      * their stacks. The original updater is called with the
 80  
      * result of the convertion.      
 81  
      */
 82  
     public void end(ReadContext context) throws Exception {
 83  26
         if (originalUpdater != null) {       
 84  
             // create an array of appropriate type
 85  26
             List values = (List) context.popBean();
 86  26
             originalUpdater.update(context, values);
 87  
         }
 88  26
     }    
 89  
     
 90  
     /** Construct a delegating implmentation that wraps the real bean creator */
 91  
     public MappingAction next(
 92  
         String namespace,
 93  
         String name,
 94  
         Attributes attributes,
 95  
         ReadContext context)
 96  
         throws Exception {
 97  65
         originalUpdater = context.getCurrentUpdater();
 98  65
         MappingAction nextBindAction = BeanBindAction.INSTANCE;
 99  65
         beanMapping.setDelegate(nextBindAction);
 100  65
         return beanMapping;
 101  
     }
 102  
 
 103  
     
 104  
     
 105  
     /** Updates a list by adding the new value */
 106  52
     private static class ListUpdater implements Updater {
 107  
         /** Singleton */
 108  91
         private static final ListUpdater INSTANCE = new ListUpdater();
 109  
         
 110  
         /** Update by adding the new value to the list */
 111  
         public void update(Context context, Object newValue) {
 112  65
             List values = (List) context.getBean();
 113  65
             values.add(newValue);
 114  65
         }
 115  
         
 116  
     }
 117  
     
 118  
     private static class BeanMapping extends MappingAction.Base {
 119  
         private MappingAction delegate;
 120  
         
 121  143
         BeanMapping() {}
 122  
         
 123  
 
 124  
         /**
 125  
          * Gets the action to which the bean binding is delegated.
 126  
          * @return <code>MappingAction</code> delegate, not null
 127  
          */
 128  
         MappingAction getDelegate() {
 129  0
             return delegate;
 130  
         }
 131  
 
 132  
         /**
 133  
          * Sets the action to which the bean binding is delegated.
 134  
          * @param action< code>MappingAction</code> delegate, not null
 135  
          */
 136  
         void setDelegate(MappingAction action) {
 137  65
             delegate = action;
 138  65
         }
 139  
         
 140  
         /** Push updater and then delegate */
 141  
         public MappingAction begin(
 142  
             String namespace,
 143  
             String name,
 144  
             Attributes attributes,
 145  
             ReadContext context)
 146  
             throws Exception {
 147  65
             context.pushUpdater(ListUpdater.INSTANCE);
 148  65
             delegate = delegate.begin(namespace, name, attributes, context);
 149  65
             return this;
 150  
         }
 151  
 
 152  
         /** Delegate to delegate (Doh!) */
 153  
         public void body(String text, ReadContext context) throws Exception {
 154  65
             delegate.body(text, context);
 155  65
         }
 156  
 
 157  
         /** Call delegate then pop <code>Updater</code> */
 158  
         public void end(ReadContext context) throws Exception {
 159  65
             delegate.end(context);
 160  65
             Updater updater = context.popUpdater();
 161  65
         }
 162  
 
 163  
         /** Use delegate to create next action */
 164  
         public MappingAction next(
 165  
             String namespace,
 166  
             String name,
 167  
             Attributes attributes,
 168  
             ReadContext context)
 169  
             throws Exception {
 170  104
             return delegate.next(namespace, name, attributes, context);
 171  
         }
 172  
 
 173  
 
 174  
     }
 175  
 }