Coverage Report - org.apache.shindig.social.core.util.xstream.GuiceBeanConverter
 
Classes in this File Line Coverage Branch Coverage Complexity
GuiceBeanConverter
93%
39/42
70%
14/20
0
GuiceBeanConverter$1
90%
18/20
88%
7/8
0
GuiceBeanConverter$DuplicateFieldException
0%
0/2
N/A
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements. See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License. You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied. See the License for the
 16  
  * specific language governing permissions and limitations under the License.
 17  
  */
 18  
 package org.apache.shindig.social.core.util.xstream;
 19  
 
 20  
 import com.google.inject.Injector;
 21  
 
 22  
 import com.thoughtworks.xstream.converters.ConversionException;
 23  
 import com.thoughtworks.xstream.converters.Converter;
 24  
 import com.thoughtworks.xstream.converters.MarshallingContext;
 25  
 import com.thoughtworks.xstream.converters.UnmarshallingContext;
 26  
 import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
 27  
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 28  
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
 29  
 import com.thoughtworks.xstream.mapper.Mapper;
 30  
 
 31  
 import org.apache.shindig.social.opensocial.model.Exportablebean;
 32  
 
 33  
 import java.util.Collection;
 34  
 import java.util.Iterator;
 35  
 
 36  
 /**
 37  
  * 
 38  
  */
 39  1560
 public class GuiceBeanConverter implements Converter {
 40  
   private Mapper mapper;
 41  
   private GuiceBeanProvider beanProvider;
 42  
 
 43  
   public GuiceBeanConverter(Mapper mapper, Injector injector) {
 44  222
     this(mapper, new GuiceBeanProvider(injector));
 45  222
   }
 46  
 
 47  222
   public GuiceBeanConverter(Mapper mapper, GuiceBeanProvider beanProvider) {
 48  222
     this.mapper = mapper;
 49  222
     this.beanProvider = beanProvider;
 50  222
   }
 51  
 
 52  
   /**
 53  
    * Only checks for the availability of a public default constructor. If you
 54  
    * need stricter checks, subclass JavaBeanConverter
 55  
    */
 56  
   public boolean canConvert(Class type) {
 57  486
     if ( type == null ) {
 58  0
       return false;
 59  
     }
 60  486
     if (Object.class.equals(type)) {
 61  316
       return false;
 62  
     }
 63  170
     if ( type.isInterface() ) {
 64  4
       return true;
 65  
     }
 66  379
     for (Class<?> iff : type.getInterfaces()) {
 67  246
       if (iff.isAnnotationPresent(Exportablebean.class)) {
 68  33
         return true;
 69  
       }
 70  
     }
 71  133
     return canConvert(type.getSuperclass());
 72  
   }
 73  
 
 74  
   public void marshal(final Object source,
 75  
       final HierarchicalStreamWriter writer, final MarshallingContext context) {
 76  73
     beanProvider.visitSerializableProperties(source,
 77  
         new GuiceBeanProvider.Visitor() {
 78  
           public boolean shouldVisit(String name, Class<?> definedIn) {
 79  978
             return mapper.shouldSerializeMember(definedIn, name);
 80  
           }
 81  
 
 82  
           public void visit(String propertyName, Class<?> fieldType,
 83  
               Class<?> definedIn, Object newObj) {
 84  962
             if (newObj != null) {
 85  278
               Mapper.ImplicitCollectionMapping mapping = mapper
 86  
                   .getImplicitCollectionDefForFieldName(source.getClass(),
 87  
                       propertyName);
 88  278
               if (mapping != null) {
 89  38
                 if (mapping.getItemFieldName() != null) {
 90  38
                   Collection<?> list = (Collection<?>) newObj;
 91  38
                   for (Iterator<?> iter = list.iterator(); iter.hasNext();) {
 92  64
                     Object obj = iter.next();
 93  64
                     writeField(propertyName, mapping.getItemFieldName(),
 94  
                         mapping.getItemType(), definedIn, obj);
 95  64
                   }
 96  38
                 } else {
 97  0
                   context.convertAnother(newObj);
 98  
                 }
 99  0
               } else {
 100  240
                 writeField(propertyName, propertyName, fieldType, definedIn,
 101  
                     newObj);
 102  
               }
 103  
             }
 104  962
           }
 105  
 
 106  73
           private void writeField(String propertyName, String aliasName,
 107  
               Class<?> fieldType, Class<?> definedIn, Object newObj) {
 108  304
             ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper
 109  
                 .serializedMember(source.getClass(), aliasName), fieldType);
 110  304
             context.convertAnother(newObj);
 111  304
             writer.endNode();
 112  
 
 113  304
           }
 114  
         });
 115  73
   }
 116  
 
 117  
   public Object unmarshal(final HierarchicalStreamReader reader,
 118  
       final UnmarshallingContext context) {
 119  4
     final Object result = instantiateNewInstance(context);
 120  
 
 121  18
     while (reader.hasMoreChildren()) {
 122  14
       reader.moveDown();
 123  
 
 124  14
       String propertyName = mapper.realMember(result.getClass(), reader
 125  
           .getNodeName());
 126  
 
 127  14
       boolean propertyExistsInClass = beanProvider.propertyDefinedInClass(
 128  
           propertyName, result.getClass());
 129  
 
 130  14
       if (propertyExistsInClass) {
 131  14
         Class<?> type = determineType(reader, result, propertyName);
 132  14
         Object value = context.convertAnother(result, type);
 133  14
         beanProvider.writeProperty(result, propertyName, value);
 134  14
       } else if (mapper.shouldSerializeMember(result.getClass(), propertyName)) {
 135  0
         throw new ConversionException("Property '" + propertyName
 136  
             + "' not defined in class " + result.getClass().getName());
 137  
       }
 138  
 
 139  14
       reader.moveUp();
 140  14
     }
 141  
 
 142  4
     return result;
 143  
   }
 144  
 
 145  
   private Object instantiateNewInstance(UnmarshallingContext context) {
 146  4
     Object result = context.currentObject();
 147  4
     if (result == null) {
 148  4
       result = beanProvider.newInstance(context.getRequiredType());
 149  
     }
 150  4
     return result;
 151  
   }
 152  
 
 153  
   private Class<?> determineType(HierarchicalStreamReader reader,
 154  
       Object result, String fieldName) {
 155  14
     final String classAttributeName = mapper.attributeForAlias("class");
 156  14
     String classAttribute = reader.getAttribute(classAttributeName);
 157  14
     if (classAttribute != null) {
 158  0
       return mapper.realClass(classAttribute);
 159  
     } else {
 160  14
       return mapper.defaultImplementationOf(beanProvider.getPropertyType(
 161  
           result, fieldName));
 162  
     }
 163  
   }
 164  
 
 165  
   /**
 166  
    * @deprecated since 1.3
 167  
    */
 168  
   public static class DuplicateFieldException extends ConversionException {
 169  
     public DuplicateFieldException(String msg) {
 170  0
       super(msg);
 171  0
     }
 172  
   }
 173  
 
 174  
 }