package org.skyscreamer.yoga.mapper; import static org.skyscreamer.yoga.util.ObjectUtil.isPrimitive; import java.io.IOException; import java.util.Map; import org.skyscreamer.yoga.model.HierarchicalModel; import org.skyscreamer.yoga.model.ListHierarchicalModel; import org.skyscreamer.yoga.model.MapHierarchicalModel; import org.skyscreamer.yoga.selector.Property; import org.skyscreamer.yoga.selector.Selector; import org.skyscreamer.yoga.util.ClassFinderStrategy; import org.skyscreamer.yoga.util.DefaultClassFinderStrategy; /** * ResultTraverser * @author solomon.duskis * */ public class ResultTraverser { protected ClassFinderStrategy _classFinderStrategy = new DefaultClassFinderStrategy(); public void traverse( Object instance, Selector selector, HierarchicalModel<?> model, YogaRequestContext context ) throws IOException { if (instance != null) { if (instance instanceof Iterable) { traverseIterable( (Iterable<?>) instance, selector, (ListHierarchicalModel<?>) model, context ); } else if (instance instanceof Map) { traverseMap( (Map<?,?>) instance, selector, (MapHierarchicalModel<?>) model, context ); } else { traversePojo( instance, selector, (MapHierarchicalModel<?>) model, context ); } } else { model.finished(); } } private <T> void addField(Selector selector, MapHierarchicalModel<?> model, YogaRequestContext context, Class<T> instanceType, boolean isPrimitive, Object value, String fieldName) throws IOException { if ( isPrimitive ) { model.addProperty( fieldName, value ); return; } Selector childSelector = selector.getChildSelector( instanceType, fieldName ); if ( value instanceof Iterable ) { traverseIterable( ( Iterable<?> ) value, childSelector, model.createChildList( fieldName ), context ); } else if ( value instanceof Map ) { traverseMap( ( Map<?, ?> ) value, childSelector, model.createChildMap( fieldName ), context ); } else { traversePojo( value, childSelector, model.createChildMap( fieldName ), context ); } } public void traverseIterable( Iterable<?> iterable, Selector selector, ListHierarchicalModel<?> model, YogaRequestContext context ) throws IOException { if ( iterable != null ) { for ( Object child : iterable ) { if (child == null || isPrimitive( child.getClass() )) { model.addValue( child ); } else if ( child instanceof Map ) { traverseMap( ( Map<?, ?> ) child, selector, model.createChildMap(), context ); } else { traversePojo( child, selector, model.createChildMap(), context ); } } context.emitEvent( model, iterable, context, selector ); } model.finished(); } private void traverseMap(Map<?, ?> map, Selector selector, MapHierarchicalModel<?> model, YogaRequestContext context) throws IOException { if ( map != null ) { for ( Map.Entry<?, ?> entry : map.entrySet() ) { String fieldName = entry.getKey().toString(); if ( selector.containsField( Map.class, fieldName ) ) { Object value = entry.getValue(); if ( value != null ) { addField( selector, model, context, Map.class, isPrimitive( value.getClass() ), value, fieldName ); } } } context.emitEvent( model, map, context, selector ); } model.finished(); } public <T> void traversePojo( T instance, Selector selector, MapHierarchicalModel<?> model, YogaRequestContext context ) throws IOException { if ( instance != null ) { Class<T> instanceType = _classFinderStrategy.findClass( instance ); for (Property<T> property : selector.getSelectedFields( instanceType )) { Object value = property.getValue( instance ); if ( value != null ) { addField( selector, model, context, instanceType, property.isPrimitive(), value, property.name() ); } } context.emitEvent( model, instance, instanceType, context, selector ); } model.finished(); } // GETTERS / SETTERS public void setClassFinderStrategy( ClassFinderStrategy classFinderStrategy ) { this._classFinderStrategy = classFinderStrategy; } public ClassFinderStrategy getClassFinderStrategy() { return _classFinderStrategy; } }