001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian 003 * Thomschke. 004 * 005 * All Rights Reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 * Contributors: 011 * Sebastian Thomschke - initial implementation. 012 *******************************************************************************/ 013 package net.sf.oval.ogn; 014 015 import java.lang.reflect.AccessibleObject; 016 import java.lang.reflect.Field; 017 import java.lang.reflect.Method; 018 019 import net.sf.oval.exception.InvalidConfigurationException; 020 import net.sf.oval.internal.util.Assert; 021 import net.sf.oval.internal.util.ReflectionUtils; 022 023 /** 024 * Default object graph navigator implementation. 025 * 026 * Object path separator is a colon (.), e.g. owner.address.street 027 * 028 * The implementation currently is limited to address fields and properties. Separate items of arrays, maps or keys cannot be addressed. 029 * 030 * @author Sebastian Thomschke 031 */ 032 public class ObjectGraphNavigatorDefaultImpl implements ObjectGraphNavigator 033 { 034 public ObjectGraphNavigationResult navigateTo(final Object root, final String path) 035 throws InvalidConfigurationException 036 { 037 Assert.argumentNotNull("root", root); 038 Assert.argumentNotNull("path", path); 039 040 Object parent = null; 041 Object target = root; 042 AccessibleObject targetAccessor = null; 043 for (final String chunk : path.split("\\.")) 044 { 045 parent = target; 046 if (parent == null) return null; 047 final Field field = ReflectionUtils.getFieldRecursive(parent.getClass(), chunk); 048 if (field == null) 049 { 050 final Method getter = ReflectionUtils.getGetterRecursive(parent.getClass(), chunk); 051 if (getter == null) 052 throw new InvalidConfigurationException("Invalid object navigation path from root object class [" 053 + root.getClass().getName() + "] path: " + path); 054 targetAccessor = getter; 055 target = ReflectionUtils.invokeMethod(getter, parent); 056 } 057 else 058 { 059 targetAccessor = field; 060 target = ReflectionUtils.getFieldValue(field, parent); 061 } 062 } 063 return new ObjectGraphNavigationResult(root, path, parent, targetAccessor, target); 064 } 065 }