2014-02-17 17:58:32 -05:00
package ca.uhn.fhir.context ;
2014-02-19 17:33:46 -05:00
import static org.apache.commons.lang3.StringUtils.isBlank ;
2014-02-17 17:58:32 -05:00
import java.lang.reflect.Field ;
2014-02-19 13:02:51 -05:00
import java.lang.reflect.ParameterizedType ;
2014-02-17 17:58:32 -05:00
import java.util.ArrayList ;
2014-02-18 08:26:49 -05:00
import java.util.Arrays ;
2014-02-17 17:58:32 -05:00
import java.util.HashMap ;
import java.util.HashSet ;
2014-02-18 18:10:50 -05:00
import java.util.Iterator ;
2014-02-19 11:59:12 -05:00
import java.util.LinkedList ;
2014-02-17 17:58:32 -05:00
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
2014-02-19 11:59:12 -05:00
import java.util.TreeMap ;
2014-02-17 17:58:32 -05:00
import ca.uhn.fhir.model.api.CodeableConceptElement ;
import ca.uhn.fhir.model.api.ICodeEnum ;
import ca.uhn.fhir.model.api.ICompositeDatatype ;
import ca.uhn.fhir.model.api.ICompositeElement ;
import ca.uhn.fhir.model.api.IDatatype ;
import ca.uhn.fhir.model.api.IElement ;
import ca.uhn.fhir.model.api.IPrimitiveDatatype ;
import ca.uhn.fhir.model.api.IResource ;
import ca.uhn.fhir.model.api.ResourceReference ;
2014-02-18 08:26:49 -05:00
import ca.uhn.fhir.model.api.annotation.Child ;
import ca.uhn.fhir.model.api.annotation.ChildResource ;
import ca.uhn.fhir.model.api.annotation.Choice ;
2014-02-18 18:10:50 -05:00
import ca.uhn.fhir.model.api.annotation.CodeTableDef ;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.model.api.annotation.DatatypeDef ;
import ca.uhn.fhir.model.api.annotation.Narrative ;
2014-02-18 18:10:50 -05:00
import ca.uhn.fhir.model.api.annotation.ResourceDef ;
import ca.uhn.fhir.model.datatype.ICodedDatatype ;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.model.datatype.NarrativeDt ;
2014-02-17 17:58:32 -05:00
class ModelScanner {
private static final org . slf4j . Logger ourLog = org . slf4j . LoggerFactory . getLogger ( ModelScanner . class ) ;
2014-02-18 18:10:50 -05:00
private Map < Class < ? extends IElement > , BaseRuntimeElementDefinition < ? > > myClassToElementDefinitions = new HashMap < Class < ? extends IElement > , BaseRuntimeElementDefinition < ? > > ( ) ;
private Map < String , RuntimeResourceDefinition > myNameToResourceDefinitions = new HashMap < String , RuntimeResourceDefinition > ( ) ;
2014-02-18 08:26:49 -05:00
private Set < Class < ? extends IElement > > myScanAlso = new HashSet < Class < ? extends IElement > > ( ) ;
2014-02-19 11:59:12 -05:00
private Set < Class < ? extends ICodeEnum > > myScanAlsoCodeTable = new HashSet < Class < ? extends ICodeEnum > > ( ) ;
2014-02-18 18:10:50 -05:00
2014-02-17 17:58:32 -05:00
// private Map<String, RuntimeResourceDefinition>
// myNameToDatatypeDefinitions = new HashMap<String,
// RuntimeDatatypeDefinition>();
2014-02-18 08:26:49 -05:00
public Map < String , RuntimeResourceDefinition > getNameToResourceDefinitions ( ) {
2014-02-18 18:10:50 -05:00
return ( myNameToResourceDefinitions ) ;
2014-02-18 08:26:49 -05:00
}
2014-02-17 17:58:32 -05:00
ModelScanner ( Class < ? extends IResource > . . . theResourceTypes ) throws ConfigurationException {
2014-02-18 18:10:50 -05:00
Set < Class < ? extends IElement > > toScan = new HashSet < Class < ? extends IElement > > ( Arrays . asList ( theResourceTypes ) ) ;
2014-02-19 11:59:12 -05:00
toScan . add ( NarrativeDt . class ) ;
2014-02-18 18:10:50 -05:00
do {
for ( Class < ? extends IElement > nextClass : toScan ) {
scan ( nextClass ) ;
}
2014-02-19 11:59:12 -05:00
for ( Iterator < Class < ? extends IElement > > iter = myScanAlso . iterator ( ) ; iter . hasNext ( ) ; ) {
2014-02-18 18:10:50 -05:00
if ( myClassToElementDefinitions . containsKey ( iter . next ( ) ) ) {
iter . remove ( ) ;
}
}
toScan . clear ( ) ;
toScan . addAll ( myScanAlso ) ;
myScanAlso . clear ( ) ;
2014-02-19 13:02:51 -05:00
} while ( ! toScan . isEmpty ( ) ) ;
2014-02-19 11:59:12 -05:00
2014-02-18 18:10:50 -05:00
for ( BaseRuntimeElementDefinition < ? > next : myClassToElementDefinitions . values ( ) ) {
next . sealAndInitialize ( myClassToElementDefinitions ) ;
2014-02-17 17:58:32 -05:00
}
2014-02-19 11:59:12 -05:00
ourLog . info ( " Done scanning FHIR library, found {} model entries " , myClassToElementDefinitions . size ( ) ) ;
2014-02-17 17:58:32 -05:00
}
private String scan ( Class < ? extends IElement > theClass ) throws ConfigurationException {
2014-02-18 18:10:50 -05:00
BaseRuntimeElementDefinition < ? > existingDef = myClassToElementDefinitions . get ( theClass ) ;
2014-02-17 17:58:32 -05:00
if ( existingDef ! = null ) {
return existingDef . getName ( ) ;
}
2014-02-18 18:10:50 -05:00
ResourceDef resourceDefinition = theClass . getAnnotation ( ResourceDef . class ) ;
2014-02-17 17:58:32 -05:00
if ( resourceDefinition ! = null ) {
if ( ! IResource . class . isAssignableFrom ( theClass ) ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Resource type contains a @ " + ResourceDef . class . getSimpleName ( ) + " annotation but does not implement " + IResource . class . getCanonicalName ( ) + " : "
+ theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
@SuppressWarnings ( " unchecked " )
Class < ? extends IResource > resClass = ( Class < ? extends IResource > ) theClass ;
return scanResource ( resClass , resourceDefinition ) ;
}
2014-02-18 18:10:50 -05:00
DatatypeDef datatypeDefinition = theClass . getAnnotation ( DatatypeDef . class ) ;
2014-02-17 17:58:32 -05:00
if ( datatypeDefinition ! = null ) {
if ( ICompositeDatatype . class . isAssignableFrom ( theClass ) ) {
@SuppressWarnings ( " unchecked " )
Class < ? extends ICompositeDatatype > resClass = ( Class < ? extends ICompositeDatatype > ) theClass ;
return scanCompositeDatatype ( resClass , datatypeDefinition ) ;
} else if ( IPrimitiveDatatype . class . isAssignableFrom ( theClass ) ) {
2014-02-19 11:59:12 -05:00
@SuppressWarnings ( { " unchecked " , " rawtypes " } )
2014-02-17 17:58:32 -05:00
Class < ? extends IPrimitiveDatatype > resClass = ( Class < ? extends IPrimitiveDatatype > ) theClass ;
return scanPrimitiveDatatype ( resClass , datatypeDefinition ) ;
} else {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Resource type contains a @ " + DatatypeDef . class . getSimpleName ( ) + " annotation but does not implement " + IDatatype . class . getCanonicalName ( ) + " : "
+ theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
}
2014-02-18 18:10:50 -05:00
CodeTableDef codeTableDefinition = theClass . getAnnotation ( CodeTableDef . class ) ;
if ( codeTableDefinition ! = null ) {
if ( ICodeEnum . class . isAssignableFrom ( theClass ) ) {
@SuppressWarnings ( " unchecked " )
Class < ? extends ICodeEnum > resClass = ( Class < ? extends ICodeEnum > ) theClass ;
return scanCodeTable ( resClass , codeTableDefinition ) ;
} else {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Resource type contains a @ " + CodeTableDef . class . getSimpleName ( ) + " annotation but does not implement " + ICodeEnum . class . getCanonicalName ( ) + " : "
+ theClass . getCanonicalName ( ) ) ;
2014-02-18 18:10:50 -05:00
}
}
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Resource type does not contain a @ " + ResourceDef . class . getSimpleName ( ) + " annotation or a @ " + DatatypeDef . class . getSimpleName ( ) + " annotation: "
+ theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
2014-02-18 18:10:50 -05:00
private String scanCompositeDatatype ( Class < ? extends ICompositeDatatype > theClass , DatatypeDef theDatatypeDefinition ) {
2014-02-17 17:58:32 -05:00
ourLog . debug ( " Scanning resource class: {} " , theClass . getName ( ) ) ;
String resourceName = theDatatypeDefinition . name ( ) ;
if ( isBlank ( resourceName ) ) {
2014-02-18 18:10:50 -05:00
throw new ConfigurationException ( " Resource type @ " + ResourceDef . class . getSimpleName ( ) + " annotation contains no resource name: " + theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
RuntimeCompositeDatatypeDefinition resourceDef = new RuntimeCompositeDatatypeDefinition ( resourceName , theClass ) ;
2014-02-18 18:10:50 -05:00
myClassToElementDefinitions . put ( theClass , resourceDef ) ;
2014-02-17 17:58:32 -05:00
2014-02-19 13:02:51 -05:00
scanCompositeElementForChildren ( theClass , resourceDef , null ) ;
2014-02-17 17:58:32 -05:00
return resourceName ;
}
2014-02-18 18:10:50 -05:00
private String scanPrimitiveDatatype ( Class < ? extends IPrimitiveDatatype > theClass , DatatypeDef theDatatypeDefinition ) {
2014-02-17 17:58:32 -05:00
ourLog . debug ( " Scanning resource class: {} " , theClass . getName ( ) ) ;
String resourceName = theDatatypeDefinition . name ( ) ;
if ( isBlank ( resourceName ) ) {
2014-02-18 18:10:50 -05:00
throw new ConfigurationException ( " Resource type @ " + ResourceDef . class . getSimpleName ( ) + " annotation contains no resource name: " + theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
RuntimePrimitiveDatatypeDefinition resourceDef = new RuntimePrimitiveDatatypeDefinition ( resourceName , theClass ) ;
2014-02-18 18:10:50 -05:00
myClassToElementDefinitions . put ( theClass , resourceDef ) ;
2014-02-17 17:58:32 -05:00
return resourceName ;
}
2014-02-18 18:10:50 -05:00
private String scanResource ( Class < ? extends IResource > theClass , ResourceDef resourceDefinition ) {
2014-02-17 17:58:32 -05:00
ourLog . debug ( " Scanning resource class: {} " , theClass . getName ( ) ) ;
String resourceName = resourceDefinition . name ( ) ;
if ( isBlank ( resourceName ) ) {
2014-02-18 18:10:50 -05:00
throw new ConfigurationException ( " Resource type @ " + ResourceDef . class . getSimpleName ( ) + " annotation contains no resource name: " + theClass . getCanonicalName ( ) ) ;
2014-02-17 17:58:32 -05:00
}
2014-02-18 18:10:50 -05:00
if ( myNameToResourceDefinitions . containsKey ( resourceName ) ) {
if ( ! myNameToResourceDefinitions . get ( resourceName ) . getImplementingClass ( ) . equals ( theClass ) ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Detected duplicate element name ' " + resourceName + " ' in types ' " + theClass . getCanonicalName ( ) + " ' and ' "
+ myNameToResourceDefinitions . get ( resourceName ) . getImplementingClass ( ) + " ' " ) ;
2014-02-17 17:58:32 -05:00
}
return resourceName ;
}
RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition ( theClass , resourceName ) ;
2014-02-18 18:10:50 -05:00
myClassToElementDefinitions . put ( theClass , resourceDef ) ;
myNameToResourceDefinitions . put ( resourceName , resourceDef ) ;
2014-02-17 17:58:32 -05:00
2014-02-19 13:02:51 -05:00
scanCompositeElementForChildren ( theClass , resourceDef , resourceDefinition . identifierOrder ( ) ) ;
2014-02-17 17:58:32 -05:00
return resourceName ;
}
2014-02-19 11:59:12 -05:00
@SuppressWarnings ( " unchecked " )
2014-02-19 13:02:51 -05:00
private void scanCompositeElementForChildren ( Class < ? extends ICompositeElement > theClass , BaseRuntimeElementCompositeDefinition < ? > theDefinition , Integer theIdentifierOrder ) {
2014-02-17 17:58:32 -05:00
Set < String > elementNames = new HashSet < String > ( ) ;
2014-02-19 11:59:12 -05:00
TreeMap < Integer , BaseRuntimeChildDefinition > orderToElementDef = new TreeMap < Integer , BaseRuntimeChildDefinition > ( ) ;
LinkedList < Class < ? extends ICompositeElement > > classes = new LinkedList < Class < ? extends ICompositeElement > > ( ) ;
Class < ? extends ICompositeElement > current = theClass ;
do {
classes . push ( current ) ;
if ( ICompositeElement . class . isAssignableFrom ( current . getSuperclass ( ) ) ) {
current = ( Class < ? extends ICompositeElement > ) current . getSuperclass ( ) ;
2014-02-19 17:33:46 -05:00
} else {
2014-02-19 11:59:12 -05:00
current = null ;
}
2014-02-19 17:33:46 -05:00
} while ( current ! = null ) ;
2014-02-19 11:59:12 -05:00
for ( Class < ? extends ICompositeElement > next : classes ) {
scanCompositeElementForChildren ( next , theDefinition , elementNames , orderToElementDef ) ;
}
2014-02-19 13:02:51 -05:00
while ( orderToElementDef . firstKey ( ) < 0 ) {
BaseRuntimeChildDefinition elementDef = orderToElementDef . remove ( orderToElementDef . firstKey ( ) ) ;
if ( elementDef . getElementName ( ) . equals ( " identifier " ) ) {
orderToElementDef . put ( theIdentifierOrder , elementDef ) ;
2014-02-19 17:33:46 -05:00
} else {
2014-02-19 13:02:51 -05:00
throw new ConfigurationException ( " Don't know how to handle element: " + elementDef . getElementName ( ) ) ;
}
}
2014-02-19 17:33:46 -05:00
2014-02-19 11:59:12 -05:00
for ( int i = 0 ; i < orderToElementDef . size ( ) ; i + + ) {
if ( ! orderToElementDef . containsKey ( i ) ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Type ' " + theClass . getCanonicalName ( ) + " ' does not have a child with order " + i
+ " (in other words, there are gaps between specified child orders) " ) ;
2014-02-19 11:59:12 -05:00
}
BaseRuntimeChildDefinition next = orderToElementDef . get ( i ) ;
theDefinition . addChild ( next ) ;
}
}
2014-02-19 13:02:51 -05:00
@SuppressWarnings ( " unchecked " )
2014-02-19 17:33:46 -05:00
private void scanCompositeElementForChildren ( Class < ? extends ICompositeElement > theClass , BaseRuntimeElementCompositeDefinition < ? > theDefinition , Set < String > elementNames ,
TreeMap < Integer , BaseRuntimeChildDefinition > orderToElementDef ) {
2014-02-19 11:59:12 -05:00
for ( Field next : theClass . getDeclaredFields ( ) ) {
2014-02-19 17:33:46 -05:00
2014-02-19 11:59:12 -05:00
Narrative hasNarrative = next . getAnnotation ( Narrative . class ) ;
if ( hasNarrative ! = null ) {
RuntimeChildNarrativeDefinition def ;
try {
def = new RuntimeChildNarrativeDefinition ( next , hasNarrative . name ( ) ) ;
} catch ( Exception e ) {
throw new ConfigurationException ( " Failed to find narrative field " , e ) ;
}
theDefinition . addChild ( def ) ;
2014-02-19 17:33:46 -05:00
continue ;
2014-02-19 11:59:12 -05:00
}
2014-02-18 08:26:49 -05:00
Child element = next . getAnnotation ( Child . class ) ;
2014-02-17 17:58:32 -05:00
if ( element = = null ) {
2014-02-19 17:33:46 -05:00
ourLog . debug ( " Ignoring non-type field ' " + next . getName ( ) + " ' on target type: " + theClass ) ;
2014-02-17 17:58:32 -05:00
continue ;
}
String elementName = element . name ( ) ;
int order = element . order ( ) ;
int min = element . min ( ) ;
int max = element . max ( ) ;
2014-02-19 11:59:12 -05:00
while ( order = = Child . ORDER_UNKNOWN & & orderToElementDef . containsKey ( order ) ) {
order - - ;
}
2014-02-19 17:33:46 -05:00
2014-02-18 08:26:49 -05:00
Choice choiceAttr = element . choice ( ) ;
2014-02-17 17:58:32 -05:00
List < Class < ? extends IElement > > choiceTypes = new ArrayList < Class < ? extends IElement > > ( ) ;
for ( Class < ? extends IElement > nextChoiceType : choiceAttr . types ( ) ) {
choiceTypes . add ( nextChoiceType ) ;
}
if ( orderToElementDef . containsKey ( order ) ) {
throw new ConfigurationException ( " Detected duplicate field order ' " + order + " ' in type ' " + theClass . getCanonicalName ( ) + " ' " ) ;
}
if ( elementNames . contains ( elementName ) ) {
throw new ConfigurationException ( " Detected duplicate field name ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' " ) ;
}
2014-02-18 08:26:49 -05:00
ChildResource resRefAnnotation = next . getAnnotation ( ChildResource . class ) ;
2014-02-17 17:58:32 -05:00
if ( choiceTypes . isEmpty ( ) = = false ) {
2014-02-18 08:26:49 -05:00
/ *
* Child is a choice element
* /
myScanAlso . addAll ( choiceTypes ) ;
RuntimeChildChoiceDefinition def = new RuntimeChildChoiceDefinition ( next , elementName , min , max , choiceTypes ) ;
2014-02-17 17:58:32 -05:00
orderToElementDef . put ( order , def ) ;
} else if ( ResourceReference . class . isAssignableFrom ( next . getType ( ) ) ) {
2014-02-18 08:26:49 -05:00
/ *
* Child is a resource reference
* /
2014-02-17 17:58:32 -05:00
if ( resRefAnnotation = = null ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Field ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' is a resource reference but does not have a @ "
+ ChildResource . class . getSimpleName ( ) + " annotation " ) ;
2014-02-17 17:58:32 -05:00
}
2014-02-18 08:26:49 -05:00
Class < ? extends IResource > [ ] refType = resRefAnnotation . types ( ) ;
List < Class < ? extends IResource > > refTypesList = Arrays . asList ( refType ) ;
myScanAlso . addAll ( refTypesList ) ;
RuntimeChildResourceDefinition def = new RuntimeChildResourceDefinition ( next , elementName , min , max , refTypesList ) ;
2014-02-17 17:58:32 -05:00
orderToElementDef . put ( order , def ) ;
2014-02-18 18:10:50 -05:00
2014-02-17 17:58:32 -05:00
} else {
if ( resRefAnnotation ! = null ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Field ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' is not a resource reference but has a @ "
+ ChildResource . class . getSimpleName ( ) + " annotation " ) ;
2014-02-17 17:58:32 -05:00
}
2014-02-19 13:02:51 -05:00
Class < ? extends IDatatype > nextDatatype ;
if ( IDatatype . class . isAssignableFrom ( next . getType ( ) ) ) {
nextDatatype = ( Class < ? extends IDatatype > ) next . getType ( ) ;
} else {
2014-02-19 17:33:46 -05:00
if ( List . class . isAssignableFrom ( next . getType ( ) ) ) {
Class < ? > type = getGenericCollectionTypeOfField ( next ) ;
2014-02-19 13:02:51 -05:00
if ( IDatatype . class . isAssignableFrom ( type ) ) {
2014-02-19 17:33:46 -05:00
nextDatatype = ( Class < ? extends IDatatype > ) type ;
} else {
throw new ConfigurationException ( " Field ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' is not a resource reference and is not an instance of type "
+ IDatatype . class . getName ( ) ) ;
2014-02-19 13:02:51 -05:00
}
2014-02-19 17:33:46 -05:00
} else {
/ * TODO : detect when someone has used a different collection ( set , etc . ) and
* give a nice error that indicates that they need to use List . .
* /
throw new ConfigurationException ( " Field ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' is not a resource reference and is not an instance of type "
+ IDatatype . class . getName ( ) ) ;
2014-02-19 13:02:51 -05:00
}
2014-02-17 17:58:32 -05:00
}
2014-02-18 18:10:50 -05:00
myScanAlso . add ( nextDatatype ) ;
2014-02-18 08:26:49 -05:00
2014-02-18 18:10:50 -05:00
BaseRuntimeChildDatatypeDefinition def ;
2014-02-18 08:26:49 -05:00
if ( IPrimitiveDatatype . class . isAssignableFrom ( next . getType ( ) ) ) {
2014-02-18 18:10:50 -05:00
def = new RuntimeChildPrimitiveDatatypeDefinition ( next , elementName , min , max , nextDatatype ) ;
} else {
def = new RuntimeChildCompositeDatatypeDefinition ( next , elementName , min , max , nextDatatype ) ;
}
CodeableConceptElement concept = next . getAnnotation ( CodeableConceptElement . class ) ;
if ( concept ! = null ) {
if ( ! ICodedDatatype . class . isAssignableFrom ( nextDatatype ) ) {
2014-02-19 17:33:46 -05:00
throw new ConfigurationException ( " Field ' " + elementName + " ' in type ' " + theClass . getCanonicalName ( ) + " ' is marked as @ " + CodeableConceptElement . class . getCanonicalName ( )
+ " but type is not a subtype of " + ICodedDatatype . class . getName ( ) ) ;
2014-02-18 18:10:50 -05:00
} else {
Class < ? extends ICodeEnum > type = concept . type ( ) ;
2014-02-19 11:59:12 -05:00
myScanAlsoCodeTable . add ( type ) ;
2014-02-18 18:10:50 -05:00
def . setCodeType ( type ) ;
}
2014-02-17 17:58:32 -05:00
}
2014-02-18 08:26:49 -05:00
2014-02-18 18:10:50 -05:00
orderToElementDef . put ( order , def ) ;
// TODO: handle codes
// if (concept != null) {
// Class<? extends ICodeEnum> codeType = concept.type();
// String codeTableName = scanCodeTable(codeType);
// @SuppressWarnings("unchecked")
2014-02-19 11:59:12 -05:00
// String datatypeName = scan((Class<? extends IDatatype>)
// next.getType());
// RuntimeChildCompositeDatatypeDefinition def = new
// RuntimeChildCompositeDatatypeDefinition(next, elementName,
// datatypeName, min, max, codeTableName);
2014-02-18 18:10:50 -05:00
// orderToElementDef.put(order, def);
// } else {
// @SuppressWarnings("unchecked")
// orderToElementDef.put(order, def);
// }
2014-02-17 17:58:32 -05:00
}
elementNames . add ( elementName ) ;
}
}
2014-02-19 17:33:46 -05:00
private static Class < ? > getGenericCollectionTypeOfField ( Field next ) {
// Type genericSuperclass = next.getType().getGenericSuperclass();
Class < ? > type ;
// if (genericSuperclass == null) {
ParameterizedType collectionType = ( ParameterizedType ) next . getGenericType ( ) ;
type = ( Class < ? > ) collectionType . getActualTypeArguments ( ) [ 0 ] ;
// }else {
// Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
// type = (Class<?>) actualTypeArguments[0];
// }
return type ;
}
2014-02-18 18:10:50 -05:00
private String scanCodeTable ( Class < ? extends ICodeEnum > theCodeType , CodeTableDef theCodeTableDefinition ) {
return null ; // TODO: implement
2014-02-17 17:58:32 -05:00
}
}