private int createScopedFactoryMethods ( JCodeModel codeModel , JDefinedClass factoryClass , Collection < ScopedElementInfo > scopedElementInfos , JDefinedClass targetClass , JClass xmlElementDeclModelClass , JClass jaxbElementModelClass , JClass qNameModelClass ) { int createdMethods = 0 ; NEXT : for ( ScopedElementInfo info : scopedElementInfos ) { String dotClazz = targetClass . fullName ( ) + ".class" ; // First check that such factory method has not yet been created. It can be the case if target class // is substituted with e.g. two candidates, each candidate having a field with the same name. // FIXME: Could it be the case that these two fields have different namespaces? for ( JMethod method : factoryClass . methods ( ) ) { JAnnotationUse xmlElementDeclAnnotation = getAnnotation ( method , xmlElementDeclModelClass ) ; JExpression scope = getAnnotationMemberExpression ( xmlElementDeclAnnotation , "scope" ) ; JExpression name = getAnnotationMemberExpression ( xmlElementDeclAnnotation , "name" ) ; if ( scope != null && dotClazz . equals ( generableToString ( scope ) ) && generableToString ( info . name ) . equals ( generableToString ( name ) ) ) { continue NEXT ; } } // Generate the scoped factory method: // @XmlElementDecl(..., scope = T.class) // public JAXBElement<X> createT...(X value) { return new JAXBElement<...>(QNAME, X.class, T.class, value); } StringBuilder methodName = new StringBuilder ( ) ; JDefinedClass container = targetClass ; // To avoid potential name conflicts method name starts with scope class name: while ( true ) { methodName . insert ( 0 , container . name ( ) ) ; if ( container . parentContainer ( ) . isClass ( ) ) { container = ( JDefinedClass ) container . parentContainer ( ) ; } else { break ; } } methodName . insert ( 0 , "create" ) . append ( NameConverter . standard . toPropertyName ( generableToString ( info . name ) ) ) ; JClass jaxbElementType = jaxbElementModelClass . narrow ( info . type ) ; JMethod method = factoryClass . method ( JMod . PUBLIC , jaxbElementType , methodName . toString ( ) ) ; method . annotate ( xmlElementDeclModelClass ) . param ( "namespace" , info . namespace ) . param ( "name" , info . name ) . param ( "scope" , targetClass ) ; JInvocation qname = JExpr . _new ( qNameModelClass ) . arg ( info . namespace ) . arg ( info . name ) ; // The primitive type get boxed and cannot be a narrowed class. However in general case if this type // is a collection (i.e. is narrowed), then it should be additionally casted to Class (e.g. "(Class) List.class"). JClass declaredType = info . type . boxify ( ) ; method . body ( ) . _return ( JExpr . _new ( jaxbElementType ) . arg ( qname ) . arg ( declaredType . erasure ( ) == declaredType ? declaredType . dotclass ( ) : JExpr . cast ( codeModel . ref ( Class . class ) , declaredType . dotclass ( ) ) ) . arg ( targetClass . dotclass ( ) ) . arg ( method . param ( info . type , "value" ) ) ) ; createdMethods ++ ; } return createdMethods ; }
Create additional factory methods with a new scope for elements that should be scoped .