dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #28104
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14004: type descriptor controller, wip
------------------------------------------------------------
revno: 14004
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-02-13 12:51:55 +0700
message:
type descriptor controller, wip
added:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/annotation/Description.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TypeController.java
modified:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java
dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/SystemSettingController.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/WebUtils.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/common/BaseIdentifiableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java 2013-10-01 12:13:34 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java 2014-02-13 05:51:55 +0000
@@ -28,20 +28,6 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.lang.Validate;
-import org.hisp.dhis.common.view.SharingBasicView;
-import org.hisp.dhis.common.view.SharingDetailedView;
-import org.hisp.dhis.common.view.SharingExportView;
-import org.hisp.dhis.user.User;
-import org.hisp.dhis.user.UserGroupAccess;
-
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
@@ -49,6 +35,19 @@
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.apache.commons.lang.Validate;
+import org.hisp.dhis.common.view.SharingBasicView;
+import org.hisp.dhis.common.view.SharingDetailedView;
+import org.hisp.dhis.common.view.SharingExportView;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserGroupAccess;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
/**
* @author Bob Jolliffe
@@ -347,7 +346,7 @@
/**
* Class check uses isAssignableFrom and get-methods to handle proxied objects.
*/
- @Override
+ @Override
public boolean equals( Object o )
{
if ( this == o )
@@ -359,7 +358,7 @@
{
return false;
}
-
+
if ( !getClass().isAssignableFrom( o.getClass() ) )
{
return false;
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/annotation/Description.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/annotation/Description.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/annotation/Description.java 2014-02-13 05:51:55 +0000
@@ -0,0 +1,44 @@
+package org.hisp.dhis.common.annotation;
+
+/*
+ * Copyright (c) 2004-2013, 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 java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Target( { ElementType.METHOD } )
+@Retention( RetentionPolicy.RUNTIME )
+public @interface Description
+{
+ String value();
+}
=== 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 2014-02-10 08:47:17 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java 2014-02-13 05:51:55 +0000
@@ -28,11 +28,12 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.google.common.collect.Maps;
import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.annotation.Description;
import org.hisp.dhis.system.util.functional.Function1;
import org.hisp.dhis.system.util.functional.Predicate;
import org.springframework.util.StringUtils;
@@ -525,24 +526,101 @@
return fieldName;
}
- private static Map<Class<?>, Map<String, MethodDescriptor>> classMapCache = Maps.newHashMap();
+ private static Map<Class<?>, Map<String, PropertyDescriptor>> classMapCache = Maps.newHashMap();
- public static class MethodDescriptor
+ public static class PropertyDescriptor
{
+ private String name;
+
+ private String description;
+
+ private String xmlName;
+
+ private boolean xmlAttribute;
+
+ private String xmlCollectionName;
+
+ private Class<?> clazz;
+
private Method method;
private boolean collection;
private boolean identifiableObject;
- private Map<String, MethodDescriptor> objects;
+ private Map<String, PropertyDescriptor> objects;
- private MethodDescriptor( Method method )
+ private PropertyDescriptor( Method method )
{
this.method = method;
}
- @JsonIgnore
+ @JsonProperty
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+
+ @JsonProperty
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public void setDescription( String description )
+ {
+ this.description = description;
+ }
+
+ @JsonProperty
+ public String getXmlName()
+ {
+ return xmlName;
+ }
+
+ public void setXmlName( String xmlName )
+ {
+ this.xmlName = xmlName;
+ }
+
+ @JsonProperty
+ public boolean isXmlAttribute()
+ {
+ return xmlAttribute;
+ }
+
+ public void setXmlAttribute( boolean xmlAttribute )
+ {
+ this.xmlAttribute = xmlAttribute;
+ }
+
+ @JsonProperty
+ public String getXmlCollectionName()
+ {
+ return xmlCollectionName;
+ }
+
+ public void setXmlCollectionName( String xmlCollectionName )
+ {
+ this.xmlCollectionName = xmlCollectionName;
+ }
+
+ @JsonProperty
+ public Class<?> getClazz()
+ {
+ return clazz;
+ }
+
+ public void setClazz( Class<?> clazz )
+ {
+ this.clazz = clazz;
+ }
+
public Method getMethod()
{
return method;
@@ -576,32 +654,23 @@
}
@JsonProperty
- public Map<String, MethodDescriptor> getObjects()
+ public Map<String, PropertyDescriptor> getObjects()
{
return objects;
}
- public void setObjects( Map<String, MethodDescriptor> objects )
+ public void setObjects( Map<String, PropertyDescriptor> objects )
{
this.objects = objects;
}
-
- @Override public String toString()
- {
- return "MethodDescriptor{" +
- "method=" + method +
- ", collection=" + collection +
- ", identifiableObject=" + identifiableObject +
- '}';
- }
}
- public static Map<String, MethodDescriptor> getJacksonClassMap( Class<?> clazz )
+ public static Map<String, PropertyDescriptor> getJacksonClassMap( Class<?> clazz )
{
return getJacksonClassMap( clazz, 2 );
}
- public static Map<String, MethodDescriptor> getJacksonClassMap( Class<?> clazz, int level )
+ public static Map<String, PropertyDescriptor> getJacksonClassMap( Class<?> clazz, int level )
{
// this short-circuits the level stuff for now, need to fix this properly
if ( classMapCache.containsKey( clazz ) )
@@ -617,7 +686,7 @@
deep = true;
}
- Map<String, MethodDescriptor> output = Maps.newLinkedHashMap();
+ Map<String, PropertyDescriptor> output = Maps.newLinkedHashMap();
List<Method> allMethods = getAllMethods( clazz );
for ( Method method : allMethods )
@@ -625,7 +694,7 @@
if ( method.isAnnotationPresent( JsonProperty.class ) )
{
JsonProperty jsonProperty = method.getAnnotation( JsonProperty.class );
- MethodDescriptor descriptor = new MethodDescriptor( method );
+ PropertyDescriptor descriptor = new PropertyDescriptor( method );
String name = jsonProperty.value();
@@ -648,9 +717,30 @@
name = StringUtils.uncapitalize( name );
}
+ if ( method.isAnnotationPresent( Description.class ) )
+ {
+ Description description = method.getAnnotation( Description.class );
+ descriptor.setDescription( description.value() );
+ }
+
+ if ( method.isAnnotationPresent( JacksonXmlProperty.class ) )
+ {
+ JacksonXmlProperty jacksonXmlProperty = method.getAnnotation( JacksonXmlProperty.class );
+ descriptor.setXmlName( jacksonXmlProperty.localName() );
+ descriptor.setXmlAttribute( jacksonXmlProperty.isAttribute() );
+ }
+
+ if ( method.isAnnotationPresent( JacksonXmlElementWrapper.class ) )
+ {
+ JacksonXmlElementWrapper jacksonXmlElementWrapper = method.getAnnotation( JacksonXmlElementWrapper.class );
+ descriptor.setXmlCollectionName( jacksonXmlElementWrapper.localName() );
+ }
+
+ descriptor.setName( name );
output.put( name, descriptor );
Class<?> returnType = method.getReturnType();
+ descriptor.setClazz( returnType );
if ( IdentifiableObject.class.isAssignableFrom( returnType ) )
{
@@ -658,7 +748,7 @@
if ( deep )
{
- Map<String, MethodDescriptor> classMap = getJacksonClassMap( returnType, level );
+ Map<String, PropertyDescriptor> classMap = getJacksonClassMap( returnType, level );
descriptor.setObjects( classMap );
}
}
@@ -678,7 +768,7 @@
if ( deep )
{
- Map<String, MethodDescriptor> classMap = getJacksonClassMap( returnType, level );
+ Map<String, PropertyDescriptor> classMap = getJacksonClassMap( returnType, level );
descriptor.setObjects( classMap );
}
}
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/SystemSettingController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/SystemSettingController.java 2013-12-21 19:13:26 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/SystemSettingController.java 2014-02-13 05:51:55 +0000
@@ -28,10 +28,6 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import java.io.Serializable;
-
-import javax.servlet.http.HttpServletResponse;
-
import org.hisp.dhis.api.utils.ContextUtils;
import org.hisp.dhis.setting.SystemSettingManager;
import org.springframework.beans.factory.annotation.Autowired;
@@ -44,22 +40,25 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import javax.servlet.http.HttpServletResponse;
+import java.io.Serializable;
+
/**
* @author Lars Helge Overland
*/
@Controller
-@RequestMapping( "/systemSettings" )
+@RequestMapping("/systemSettings")
public class SystemSettingController
{
@Autowired
private SystemSettingManager systemSettingManager;
- @RequestMapping( value = "/{key}", method = RequestMethod.POST, consumes = { ContextUtils.CONTENT_TYPE_TEXT, ContextUtils.CONTENT_TYPE_HTML } )
- @PreAuthorize( "hasRole('ALL') or hasRole('F_SYSTEM_SETTING')" )
+ @RequestMapping(value = "/{key}", method = RequestMethod.POST, consumes = { ContextUtils.CONTENT_TYPE_TEXT, ContextUtils.CONTENT_TYPE_HTML })
+ @PreAuthorize("hasRole('ALL') or hasRole('F_SYSTEM_SETTING')")
public void setSystemSetting(
@PathVariable String key,
@RequestParam(required = false) String value,
- @RequestBody(required=false) String valuePayload, HttpServletResponse response )
+ @RequestBody(required = false) String valuePayload, HttpServletResponse response )
{
if ( key == null )
{
@@ -79,17 +78,17 @@
ContextUtils.okResponse( response, "System setting " + key + " set as value '" + value + "'." );
}
- @RequestMapping( value = "/{key}", method = RequestMethod.GET, produces = ContextUtils.CONTENT_TYPE_TEXT )
- public @ResponseBody String getSystemSetting( @PathVariable( "key" ) String key )
+ @RequestMapping(value = "/{key}", method = RequestMethod.GET, produces = ContextUtils.CONTENT_TYPE_TEXT)
+ public @ResponseBody String getSystemSetting( @PathVariable("key") String key )
{
Serializable setting = systemSettingManager.getSystemSetting( key );
-
+
return setting != null ? String.valueOf( setting ) : null;
}
- @RequestMapping( value = "/{key}", method = RequestMethod.DELETE )
- @PreAuthorize( "hasRole('ALL') or hasRole('F_SYSTEM_SETTING')" )
- public void removeSystemSetting( @PathVariable( "key" ) String key )
+ @RequestMapping(value = "/{key}", method = RequestMethod.DELETE)
+ @PreAuthorize("hasRole('ALL') or hasRole('F_SYSTEM_SETTING')")
+ public void removeSystemSetting( @PathVariable("key") String key )
{
systemSettingManager.deleteSystemSetting( key );
}
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TypeController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TypeController.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TypeController.java 2014-02-13 05:51:55 +0000
@@ -0,0 +1,83 @@
+package org.hisp.dhis.api.controller;
+
+/*
+ * Copyright (c) 2004-2013, 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 com.google.common.collect.Maps;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.dxf2.metadata.ExchangeClasses;
+import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.system.util.ReflectionUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.client.HttpClientErrorException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Controller
+@RequestMapping( value = "", method = RequestMethod.GET )
+public class TypeController
+{
+ @RequestMapping( value = { "/types", "/types.json" }, method = RequestMethod.GET )
+ public void getTypesJson( OutputStream outputStream ) throws IOException
+ {
+ Map<String, Map<String, ReflectionUtils.PropertyDescriptor>> output = Maps.newHashMap();
+
+ for ( Class<? extends IdentifiableObject> key : ExchangeClasses.getAllExportMap().keySet() )
+ {
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( key );
+ output.put( ExchangeClasses.getAllExportMap().get( key ), classMap );
+ }
+
+ JacksonUtils.toJson( outputStream, output );
+ }
+
+ @RequestMapping( value = { "/types/{type}", "/types/{type}.json" }, method = RequestMethod.GET )
+ public void getTypeJson( @PathVariable String type, OutputStream outputStream ) throws IOException
+ {
+ for ( Class<? extends IdentifiableObject> key : ExchangeClasses.getAllExportMap().keySet() )
+ {
+ if ( ExchangeClasses.getAllExportMap().get( key ).equals( type ) )
+ {
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( key );
+ JacksonUtils.toJson( outputStream, classMap );
+ return;
+ }
+ }
+
+ throw new HttpClientErrorException( HttpStatus.NOT_FOUND );
+ }
+}
=== modified 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 2014-02-11 04:22:08 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/WebUtils.java 2014-02-13 05:51:55 +0000
@@ -268,7 +268,7 @@
if ( include == null && exclude == null )
{
- Map<String, ReflectionUtils.MethodDescriptor> classMap = ReflectionUtils.getJacksonClassMap( objects.get( 0 ).getClass() );
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( objects.get( 0 ).getClass() );
for ( String key : classMap.keySet() )
{
@@ -277,7 +277,7 @@
}
else if ( include == null )
{
- Map<String, ReflectionUtils.MethodDescriptor> classMap = ReflectionUtils.getJacksonClassMap( objects.get( 0 ).getClass() );
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( objects.get( 0 ).getClass() );
Map<String, Map> excludeMap = parseFieldExpression( exclude );
for ( String key : classMap.keySet() )
@@ -310,7 +310,7 @@
}
Map<String, Object> output = Maps.newHashMap();
- Map<String, ReflectionUtils.MethodDescriptor> classMap = ReflectionUtils.getJacksonClassMap( object.getClass() );
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( object.getClass() );
for ( String key : fieldMap.keySet() )
{
@@ -320,7 +320,7 @@
}
Map value = fieldMap.get( key );
- ReflectionUtils.MethodDescriptor descriptor = classMap.get( key );
+ ReflectionUtils.PropertyDescriptor descriptor = classMap.get( key );
Object returned = ReflectionUtils.invokeMethod( object, descriptor.getMethod() );
if ( returned == null )
@@ -413,11 +413,11 @@
private static Map<String, Object> getIdentifiableObjectProperties( Object object, List<String> fields )
{
Map<String, Object> idProps = Maps.newLinkedHashMap();
- Map<String, ReflectionUtils.MethodDescriptor> classMap = ReflectionUtils.getJacksonClassMap( object.getClass() );
+ Map<String, ReflectionUtils.PropertyDescriptor> classMap = ReflectionUtils.getJacksonClassMap( object.getClass() );
for ( String field : fields )
{
- ReflectionUtils.MethodDescriptor descriptor = classMap.get( field );
+ ReflectionUtils.PropertyDescriptor descriptor = classMap.get( field );
if ( descriptor == null )
{