=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java' --- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java 2012-05-28 15:41:40 +0000 +++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java 2012-05-29 17:21:17 +0000 @@ -33,8 +33,10 @@ import java.lang.annotation.Annotation; import java.lang.reflect.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; /** * @author Lars Helge Overland @@ -171,10 +173,9 @@ { Field field; - try - { - field = object.getClass().getDeclaredField( fieldName ); - } catch ( NoSuchFieldException e ) + field = _findField( object.getClass(), fieldName ); + + if ( field == null ) { return false; } @@ -226,7 +227,7 @@ { for ( String getterName : getterNames ) { - method = _findMethod( target.getClass(), getterName + StringUtils.capitalize( field.getName() ), field.getType() ); + method = _findMethod( target.getClass(), getterName + StringUtils.capitalize( field.getName() ) ); if ( method != null ) { @@ -235,6 +236,8 @@ } } + System.err.println( "Did not find getter" ); + return null; } @@ -325,6 +328,20 @@ return null; } + public static List getAllFields( Class clazz ) + { + Class searchType = clazz; + List fields = new ArrayList(); + + while ( !Object.class.equals( searchType ) && searchType != null ) + { + fields.addAll( Arrays.asList( searchType.getDeclaredFields() ) ); + searchType = searchType.getSuperclass(); + } + + return fields; + } + private static Method _findMethod( Class clazz, String name ) { return _findMethod( clazz, name, new Class[0] ); @@ -341,7 +358,6 @@ for ( Method method : methods ) { if ( name.equals( method.getName() ) && (paramTypes == null || Arrays.equals( paramTypes, method.getParameterTypes() )) ) - { return method; } @@ -353,6 +369,21 @@ return null; } + public static List getAllMethods( Class clazz ) + { + Class searchType = clazz; + List methods = new ArrayList(); + + while ( searchType != null ) + { + Method[] methodArray = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods()); + methods.addAll( Arrays.asList( methodArray ) ); + searchType = searchType.getSuperclass(); + } + + return methods; + } + @SuppressWarnings( "unchecked" ) public static T invokeMethod( Object target, Method method, Object... args ) { @@ -367,4 +398,10 @@ throw new RuntimeException( e ); } } + + @SuppressWarnings( "unchecked" ) + public static T getFieldObject( Field field, T target ) + { + return (T) invokeGetterMethod( field.getName(), target ); + } } === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AbstractCrudController.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AbstractCrudController.java 2012-05-28 22:37:12 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AbstractCrudController.java 2012-05-29 17:21:17 +0000 @@ -27,7 +27,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import org.hisp.dhis.api.utils.WebLinkPopulator; +import org.hisp.dhis.api.utils.WebUtils; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.common.Pager; @@ -77,8 +77,7 @@ if ( options.hasLinks() ) { - WebLinkPopulator populator = new WebLinkPopulator( request ); - populator.addLinks( metaData ); + WebUtils.generateLinks( metaData ); } model.addAttribute( "model", metaData ); @@ -95,8 +94,7 @@ if ( options.hasLinks() ) { - WebLinkPopulator populator = new WebLinkPopulator( request ); - populator.addLinks( entity ); + WebUtils.generateLinks( entity ); } model.addAttribute( "model", entity ); @@ -235,16 +233,13 @@ try { return (T) Class.forName( getEntityName() ).newInstance(); - } - catch ( InstantiationException e ) - { - throw new RuntimeException( e ); - } - catch ( IllegalAccessException e ) - { - throw new RuntimeException( e ); - } - catch ( ClassNotFoundException e ) + } catch ( InstantiationException e ) + { + throw new RuntimeException( e ); + } catch ( IllegalAccessException e ) + { + throw new RuntimeException( e ); + } catch ( ClassNotFoundException e ) { throw new RuntimeException( e ); } === added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/WebUtils.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/WebUtils.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/WebUtils.java 2012-05-29 17:21:17 +0000 @@ -0,0 +1,199 @@ +package org.hisp.dhis.api.utils; + +/* + * Copyright (c) 2004-2012, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javassist.util.proxy.ProxyObject; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hisp.dhis.api.controller.WebMetaData; +import org.hisp.dhis.common.IdentifiableObject; +import org.hisp.dhis.common.Pager; +import org.hisp.dhis.dxf2.metadata.ExchangeClasses; +import org.hisp.dhis.system.util.ReflectionUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Morten Olav Hansen + */ +public class WebUtils +{ + private static final Log log = LogFactory.getLog( WebUtils.class ); + + @SuppressWarnings( "unchecked" ) + public static void generateLinks( WebMetaData metaData ) + { + Class baseType = null; + List fields = ReflectionUtils.getAllFields( metaData.getClass() ); + + for ( Field field : fields ) + { + if ( ReflectionUtils.isCollection( field.getName(), metaData, IdentifiableObject.class ) ) + { + List objects = new ArrayList( (Collection) ReflectionUtils.getFieldObject( field, metaData ) ); + + if ( !objects.isEmpty() ) + { + if ( baseType != null ) + { + log.warn( "baseType already set, overwriting.." ); + } + + baseType = objects.get( 0 ).getClass(); + + for ( IdentifiableObject object : objects ) + { + generateLinks( object ); + } + } + } + } + + if ( metaData.getPager() != null && baseType != null ) + { + String basePath = getBasePath( baseType ); + Pager pager = metaData.getPager(); + + if ( pager.getPage() < pager.getPageCount() ) + { + pager.setNextPage( basePath + "?page=" + (pager.getPage() + 1) ); + } + + if ( pager.getPage() > 1 ) + { + if ( (pager.getPage() - 1) == 1 ) + { + pager.setPrevPage( basePath ); + } + else + { + pager.setPrevPage( basePath + "?page=" + (pager.getPage() - 1) ); + } + + } + } + } + + @SuppressWarnings( "unchecked" ) + public static void generateLinks( IdentifiableObject identifiableObject ) + { + identifiableObject.setLink( getPathWithUid( identifiableObject ) ); + + List fields = ReflectionUtils.getAllFields( identifiableObject.getClass() ); + + for ( Field field : fields ) + { + if ( IdentifiableObject.class.isAssignableFrom( field.getType() ) ) + { + IdentifiableObject object = ReflectionUtils.getFieldObject( field, identifiableObject ); + + if ( object != null ) + { + object.setLink( getPathWithUid( object ) ); + } + } + else if ( ReflectionUtils.isCollection( field.getName(), identifiableObject, IdentifiableObject.class ) ) + { + Collection objects = (Collection) ReflectionUtils.getFieldObject( field, identifiableObject ); + + for ( IdentifiableObject object : objects ) + { + object.setLink( getPathWithUid( object ) ); + } + } + } + } + + public static HttpServletRequest getRequest() + { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } + + private static String getPathWithUid( IdentifiableObject identifiableObject ) + { + return getBasePath( identifiableObject.getClass() ) + "/" + identifiableObject.getUid(); + } + + private static String getBasePath( Class clazz ) + { + if ( ProxyObject.class.isAssignableFrom( clazz ) ) + { + clazz = clazz.getSuperclass(); + } + + String resourcePath = ExchangeClasses.getExportMap().get( clazz ); + + return getRootPath( getRequest() ) + "/" + resourcePath; + } + + private static String getRootPath( HttpServletRequest request ) + { + StringBuilder builder = new StringBuilder(); + String xForwardedProto = request.getHeader( "X-Forwarded-Proto" ); + String xForwardedPort = request.getHeader( "X-Forwarded-Port" ); + + if ( xForwardedProto != null && (xForwardedProto.equalsIgnoreCase( "http" ) || xForwardedProto.equalsIgnoreCase( "https" )) ) + { + builder.append( xForwardedProto ); + } + else + { + builder.append( request.getScheme() ); + } + + + builder.append( "://" ).append( request.getServerName() ); + + int port; + + try + { + port = Integer.parseInt( xForwardedPort ); + } catch ( NumberFormatException e ) + { + port = request.getServerPort(); + } + + if ( port != 80 && port != 443 ) + { + builder.append( ":" ).append( port ); + } + + builder.append( request.getContextPath() ); + builder.append( request.getServletPath() ); + + return builder.toString(); + } + +}