dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #30522
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15487: introduces two new services: ContextServices and LinkService. LinkService will generate links aut...
------------------------------------------------------------
revno: 15487
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Sat 2014-05-31 18:27:04 +0200
message:
introduces two new services: ContextServices and LinkService. LinkService will generate links automatic based on presence of getUid and setHepref. Also extends SchemaService with new method getDynamicSchema, auto-generates schema based on class, useful for classes that have Jackson exposed properties but have no SchemaDescriptor.
added:
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/service/
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/ContextService.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultContextService.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultLinkService.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/LinkService.java
modified:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/SchemaService.java
dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/DefaultSchemaService.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/dataelement/DataElementOperandController.java
--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk
Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/SchemaService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/SchemaService.java 2014-05-28 11:02:29 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/SchemaService.java 2014-05-31 16:27:04 +0000
@@ -35,11 +35,46 @@
*/
public interface SchemaService
{
+ /**
+ * Get schema which has been generated by a SchemaDescriptor.
+ *
+ * @param klass Class to get for
+ * @return Schema for class, or null
+ * @see org.hisp.dhis.schema.SchemaDescriptor
+ */
Schema getSchema( Class<?> klass );
+ /**
+ * Get schema if it has been described by a SchemaDescriptor, if not, it will
+ * generate a Schema dynamically from the class. Only the properties part of the
+ * Schema will be usable (together with parts which can be auto-generated like isIdentifiableObject).
+ *
+ * @param klass Class to get for
+ * @return Schema for class, or null
+ * @see org.hisp.dhis.schema.SchemaDescriptor
+ */
+ Schema getDynamicSchema( Class<?> klass );
+
+ /**
+ * Get schema which has been generated by a SchemaDescriptor by singular name.
+ *
+ * @param name Name to get Schema for, will be matched against Schema.getSingular().
+ * @return Schema for class, or null
+ * @see org.hisp.dhis.schema.SchemaDescriptor
+ */
Schema getSchemaBySingularName( String name );
+ /**
+ * Get all available schemas (which are generated with a schema descriptor).
+ *
+ * @return List of all available schemas
+ */
List<Schema> getSchemas();
+ /**
+ * Get all available schemas which have the metadata property set to true.
+ *
+ * @return List of all available metadata schemas
+ */
List<Schema> getMetadataSchemas();
}
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/DefaultSchemaService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/DefaultSchemaService.java 2014-05-28 11:24:18 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/schema/DefaultSchemaService.java 2014-05-31 16:27:04 +0000
@@ -30,6 +30,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import javassist.util.proxy.ProxyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.OrderComparator;
@@ -79,27 +80,41 @@
return null;
}
- /*
if ( ProxyFactory.isProxyClass( klass ) )
{
klass = klass.getSuperclass();
}
- */
if ( classSchemaMap.containsKey( klass ) )
{
return classSchemaMap.get( klass );
}
- if ( classSchemaMap.containsKey( klass.getSuperclass() ) )
- {
- return classSchemaMap.get( klass.getSuperclass() );
- }
-
return null;
}
@Override
+ public Schema getDynamicSchema( Class<?> klass )
+ {
+ if ( klass == null )
+ {
+ return null;
+ }
+
+ Schema schema = getSchema( klass );
+
+ if ( schema != null )
+ {
+ return schema;
+ }
+
+ schema = new Schema( klass, klass.getName(), klass.getName() );
+ schema.setProperties( propertyIntrospectorService.getProperties( schema.getKlass() ) );
+
+ return schema;
+ }
+
+ @Override
public Schema getSchemaBySingularName( String name )
{
return singularSchemaMap.get( name );
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java 2014-05-31 07:39:57 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java 2014-05-31 16:27:04 +0000
@@ -52,7 +52,7 @@
import org.hisp.dhis.user.CurrentUserService;
import org.hisp.dhis.webapi.controller.exception.NotFoundException;
import org.hisp.dhis.webapi.utils.ContextUtils;
-import org.hisp.dhis.webapi.utils.WebUtils;
+import org.hisp.dhis.webapi.utils.LinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -98,6 +98,9 @@
protected SchemaService schemaService;
@Autowired
+ protected LinkService linkService;
+
+ @Autowired
protected RenderService renderService;
@Autowired
@@ -107,7 +110,7 @@
// GET
//--------------------------------------------------------------------------
- @RequestMapping( method = RequestMethod.GET )
+ @RequestMapping(method = RequestMethod.GET)
public String getObjectList(
@RequestParam Map<String, String> parameters, Model model, HttpServletResponse response, HttpServletRequest request )
{
@@ -136,11 +139,11 @@
return StringUtils.uncapitalize( getEntitySimpleName() ) + "List";
}
- @RequestMapping( method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE } )
+ @RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public void getObjectListJson(
- @RequestParam( required = false ) String include,
- @RequestParam( required = false ) String exclude,
- @RequestParam( value = "filter", required = false ) List<String> filters,
+ @RequestParam(required = false) String include,
+ @RequestParam(required = false) String exclude,
+ @RequestParam(value = "filter", required = false) List<String> filters,
@RequestParam Map<String, String> parameters, Model model, HttpServletResponse response, HttpServletRequest request ) throws IOException
{
WebOptions options = new WebOptions( parameters );
@@ -227,8 +230,8 @@
}
- @RequestMapping( value = "/{uid}", method = RequestMethod.GET )
- public String getObject( @PathVariable( "uid" ) String uid, @RequestParam Map<String, String> parameters,
+ @RequestMapping(value = "/{uid}", method = RequestMethod.GET)
+ public String getObject( @PathVariable("uid") String uid, @RequestParam Map<String, String> parameters,
Model model, HttpServletRequest request, HttpServletResponse response ) throws Exception
{
WebOptions options = new WebOptions( parameters );
@@ -241,7 +244,7 @@
if ( options.hasLinks() )
{
- WebUtils.generateLinks( entity );
+ linkService.generateLinks( entity );
}
if ( aclService.isSupported( getEntityClass() ) )
@@ -262,7 +265,7 @@
// POST
//--------------------------------------------------------------------------
- @RequestMapping( method = RequestMethod.POST, consumes = { "application/xml", "text/xml" } )
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/xml", "text/xml" })
public void postXmlObject( HttpServletResponse response, HttpServletRequest request, InputStream input ) throws Exception
{
if ( !aclService.canCreate( currentUserService.getCurrentUser(), getEntityClass() ) )
@@ -275,7 +278,7 @@
renderService.toJson( response.getOutputStream(), summary );
}
- @RequestMapping( method = RequestMethod.POST, consumes = "application/json" )
+ @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
public void postJsonObject( HttpServletResponse response, HttpServletRequest request, InputStream input ) throws Exception
{
if ( !aclService.canCreate( currentUserService.getCurrentUser(), getEntityClass() ) )
@@ -292,9 +295,9 @@
// PUT
//--------------------------------------------------------------------------
- @RequestMapping( value = "/{uid}", method = RequestMethod.PUT, consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE } )
- @ResponseStatus( value = HttpStatus.NO_CONTENT )
- public void putXmlObject( HttpServletResponse response, HttpServletRequest request, @PathVariable( "uid" ) String uid, InputStream
+ @RequestMapping(value = "/{uid}", method = RequestMethod.PUT, consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE })
+ @ResponseStatus(value = HttpStatus.NO_CONTENT)
+ public void putXmlObject( HttpServletResponse response, HttpServletRequest request, @PathVariable("uid") String uid, InputStream
input ) throws Exception
{
T object = getEntity( uid );
@@ -317,9 +320,9 @@
renderService.toJson( response.getOutputStream(), summary );
}
- @RequestMapping( value = "/{uid}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE )
- @ResponseStatus( value = HttpStatus.NO_CONTENT )
- public void putJsonObject( HttpServletResponse response, HttpServletRequest request, @PathVariable( "uid" ) String uid, InputStream
+ @RequestMapping(value = "/{uid}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseStatus(value = HttpStatus.NO_CONTENT)
+ public void putJsonObject( HttpServletResponse response, HttpServletRequest request, @PathVariable("uid") String uid, InputStream
input ) throws Exception
{
T object = getEntity( uid );
@@ -346,9 +349,9 @@
// DELETE
//--------------------------------------------------------------------------
- @RequestMapping( value = "/{uid}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE )
- @ResponseStatus( value = HttpStatus.NO_CONTENT )
- public void deleteObject( HttpServletResponse response, HttpServletRequest request, @PathVariable( "uid" ) String uid ) throws
+ @RequestMapping(value = "/{uid}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseStatus(value = HttpStatus.NO_CONTENT)
+ public void deleteObject( HttpServletResponse response, HttpServletRequest request, @PathVariable("uid") String uid ) throws
Exception
{
T object = getEntity( uid );
@@ -452,7 +455,7 @@
{
if ( options != null && options.hasLinks() )
{
- WebUtils.generateLinks( metaData, deep );
+ linkService.generateLinks( metaData );
}
if ( !JacksonUtils.isSharingView( options.getViewClass( "basic" ) ) )
@@ -479,7 +482,7 @@
private String entitySimpleName;
- @SuppressWarnings( "unchecked" )
+ @SuppressWarnings("unchecked")
protected Class<T> getEntityClass()
{
if ( entityClass == null )
@@ -511,7 +514,7 @@
return entitySimpleName;
}
- @SuppressWarnings( "unchecked" )
+ @SuppressWarnings("unchecked")
protected T getEntityInstance()
{
try
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/dataelement/DataElementOperandController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/dataelement/DataElementOperandController.java 2014-05-28 09:57:38 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/dataelement/DataElementOperandController.java 2014-05-31 16:27:04 +0000
@@ -81,11 +81,11 @@
if ( dataElementGroup == null )
{
- entityList = new ArrayList<DataElementOperand>();
+ entityList = new ArrayList<>();
}
else
{
- entityList = new ArrayList<DataElementOperand>( dataElementOperandService.getDataElementOperandByDataElementGroup( dataElementGroup ) );
+ entityList = new ArrayList<>( dataElementOperandService.getDataElementOperandByDataElementGroup( dataElementGroup ) );
}
}
else if ( options.hasPaging() )
@@ -95,12 +95,12 @@
Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
metaData.setPager( pager );
- entityList = new ArrayList<DataElementOperand>( dataElementOperandService.getAllDataElementOperands(
+ entityList = new ArrayList<>( dataElementOperandService.getAllDataElementOperands(
pager.getOffset(), pager.getPageSize() ) );
}
else
{
- entityList = new ArrayList<DataElementOperand>( dataElementOperandService.getAllDataElementOperands() );
+ entityList = new ArrayList<>( dataElementOperandService.getAllDataElementOperands() );
}
return entityList;
=== added directory 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/service'
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/ContextService.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/ContextService.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/ContextService.java 2014-05-31 16:27:04 +0000
@@ -0,0 +1,60 @@
+package org.hisp.dhis.webapi.utils;
+
+/*
+ * Copyright (c) 2004-2014, 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 javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public interface ContextService
+{
+ /**
+ * Get full path of servlet.
+ *
+ * @return Full HREF to servlet
+ * @see javax.servlet.http.HttpServletRequest
+ */
+ String getServletPath();
+
+ /**
+ * Get HREF to context.
+ *
+ * @return Full HREF to context (context root)
+ * @see javax.servlet.http.HttpServletRequest
+ */
+ String getContextPath();
+
+ /**
+ * Get active HttpServletRequest
+ *
+ * @return HttpServletRequest
+ */
+ HttpServletRequest getRequest();
+}
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultContextService.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultContextService.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultContextService.java 2014-05-31 16:27:04 +0000
@@ -0,0 +1,95 @@
+package org.hisp.dhis.webapi.utils;
+
+/*
+ * Copyright (c) 2004-2014, 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 org.springframework.stereotype.Service;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Service
+public class DefaultContextService implements ContextService
+{
+ @Override
+ public String getServletPath()
+ {
+ HttpServletRequest request = getRequest();
+ return getContextPath() + request.getServletPath();
+ }
+
+ @Override
+ public String getContextPath()
+ {
+ HttpServletRequest request = getRequest();
+ 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() );
+
+ return builder.toString();
+ }
+
+ @Override
+ public HttpServletRequest getRequest()
+ {
+ return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+ }
+}
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultLinkService.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultLinkService.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/DefaultLinkService.java 2014-05-31 16:27:04 +0000
@@ -0,0 +1,182 @@
+package org.hisp.dhis.webapi.utils;
+
+/*
+ * Copyright (c) 2004-2014, 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.ProxyFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.collection.spi.PersistentCollection;
+import org.hisp.dhis.schema.Property;
+import org.hisp.dhis.schema.Schema;
+import org.hisp.dhis.schema.SchemaService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Service
+public class DefaultLinkService implements LinkService
+{
+ private static final Log log = LogFactory.getLog( DefaultLinkService.class );
+
+ @Autowired
+ private SchemaService schemaService;
+
+ @Autowired
+ private ContextService contextService;
+
+ @Override
+ public <T> void generateLinks( T object )
+ {
+ generateLinks( object, contextService.getServletPath() );
+ }
+
+ @Override
+ public <T> void generateLinks( T object, String hrefBase )
+ {
+ if ( Collection.class.isInstance( object ) )
+ {
+ Collection<?> collection = (Collection<?>) object;
+
+ for ( Object collectionObject : collection )
+ {
+ generateLink( collectionObject, hrefBase, false );
+ }
+ }
+ else
+ {
+ generateLink( object, hrefBase, true );
+ }
+ }
+
+ private <T> void generateLink( T object, String hrefBase, boolean deepScan )
+ {
+ Schema schema = schemaService.getDynamicSchema( object.getClass() );
+
+ if ( schema == null )
+ {
+ log.warn( "Could not find schema for object of type " + object.getClass().getName() + "." );
+ return;
+ }
+
+ generateHref( object, hrefBase );
+
+ if ( !deepScan )
+ {
+ return;
+ }
+
+ for ( Property property : schema.getProperties() )
+ {
+ try
+ {
+ // TODO should we support non-idObjects?
+ if ( property.isIdentifiableObject() )
+ {
+ Object propertyObject = property.getGetterMethod().invoke( object );
+
+ if ( propertyObject == null )
+ {
+ continue;
+ }
+
+ // unwrap hibernate PersistentCollection
+ if ( PersistentCollection.class.isAssignableFrom( propertyObject.getClass() ) )
+ {
+ PersistentCollection collection = (PersistentCollection) propertyObject;
+ propertyObject = collection.getValue();
+ }
+
+ if ( !property.isCollection() )
+ {
+ generateHref( propertyObject, hrefBase );
+ }
+ else
+ {
+ Collection<?> collection = (Collection<?>) propertyObject;
+
+ for ( Object collectionObject : collection )
+ {
+ generateHref( collectionObject, hrefBase );
+ }
+ }
+
+ }
+ }
+ catch ( InvocationTargetException | IllegalAccessException ignored )
+ {
+ }
+ }
+ }
+
+ private <T> void generateHref( T object, String hrefBase )
+ {
+ if ( object == null )
+ {
+ return;
+ }
+
+ Class<?> klass = object.getClass();
+
+ if ( ProxyFactory.isProxyClass( klass ) )
+ {
+ klass = klass.getSuperclass();
+ }
+
+ Schema schema = schemaService.getDynamicSchema( klass );
+
+ if ( !schema.haveEndpoint() )
+ {
+ return;
+ }
+
+ try
+ {
+ Method getUid = object.getClass().getMethod( "getUid" );
+ Object value = getUid.invoke( object );
+
+ if ( !String.class.isInstance( value ) )
+ {
+ log.warn( "getUid on object of type " + object.getClass().getName() + " does not return a String." );
+ return;
+ }
+
+ Method setHref = object.getClass().getMethod( "setHref", String.class );
+ setHref.invoke( object, hrefBase + schema.getApiEndpoint() + "/" + value );
+ }
+ catch ( NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored )
+ {
+ }
+ }
+}
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/LinkService.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/LinkService.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/utils/LinkService.java 2014-05-31 16:27:04 +0000
@@ -0,0 +1,55 @@
+package org.hisp.dhis.webapi.utils;
+
+/*
+ * Copyright (c) 2004-2014, 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
+ */
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public interface LinkService
+{
+ /**
+ * Generate HREF and set it using reflection, required a setHref(String) method in your class.
+ *
+ * Uses hrefBase from ContextService.getServletPath().
+ *
+ * @param object Object (can be collection) to set HREFs on
+ * @see javax.servlet.http.HttpServletRequest
+ * @see org.hisp.dhis.webapi.utils.ContextService
+ */
+ <T> void generateLinks( T object );
+
+ /**
+ * Generate HREF and set it using reflection, required a setHref(String) method in your class.
+ *
+ * @param object Object (can be collection) to set HREFs on
+ * @param hrefBase Used as starting point of HREF
+ * @see javax.servlet.http.HttpServletRequest
+ */
+ <T> void generateLinks( T object, String hrefBase );
+}