001    /*
002     * Copyright (c) 2009 The JPA-XJC Project. All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions
006     * are met:
007     *
008     *   o Redistributions of source code must retain the above copyright
009     *     notice, this  list of conditions and the following disclaimer.
010     *
011     *   o Redistributions in binary form must reproduce the above copyright
012     *     notice, this list of conditions and the following disclaimer in
013     *     the documentation and/or other materials provided with the
014     *     distribution.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE JPA-XJC PROJECT AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
018     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
019     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JPA-XJC PROJECT OR
020     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
021     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
022     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
023     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
024     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
025     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
026     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     *
028     * $Id: PluginImpl.java 101 2010-08-18 20:44:45Z schulte2005 $
029     *
030     */
031    package net.sourceforge.jpaxjc;
032    
033    import com.sun.codemodel.JAnnotationArrayMember;
034    import com.sun.codemodel.JAnnotationUse;
035    import com.sun.codemodel.JBlock;
036    import com.sun.codemodel.JCatchBlock;
037    import com.sun.codemodel.JCodeModel;
038    import com.sun.codemodel.JConditional;
039    import com.sun.codemodel.JDefinedClass;
040    import com.sun.codemodel.JExpr;
041    import com.sun.codemodel.JFieldVar;
042    import com.sun.codemodel.JMethod;
043    import com.sun.codemodel.JMod;
044    import com.sun.codemodel.JOp;
045    import com.sun.codemodel.JTryBlock;
046    import com.sun.codemodel.JType;
047    import com.sun.codemodel.JVar;
048    import net.sourceforge.jpaxjc.ns.persistence.Persistence;
049    import net.sourceforge.jpaxjc.ns.persistence.orm.AccessType;
050    import net.sourceforge.jpaxjc.ns.persistence.orm.AssociationOverride;
051    import net.sourceforge.jpaxjc.ns.persistence.orm.AttributeOverride;
052    import net.sourceforge.jpaxjc.ns.persistence.orm.Attributes;
053    import net.sourceforge.jpaxjc.ns.persistence.orm.Basic;
054    import net.sourceforge.jpaxjc.ns.persistence.orm.CascadeType;
055    import net.sourceforge.jpaxjc.ns.persistence.orm.Column;
056    import net.sourceforge.jpaxjc.ns.persistence.orm.ColumnResult;
057    import net.sourceforge.jpaxjc.ns.persistence.orm.DiscriminatorColumn;
058    import net.sourceforge.jpaxjc.ns.persistence.orm.Embeddable;
059    import net.sourceforge.jpaxjc.ns.persistence.orm.EmbeddableAttributes;
060    import net.sourceforge.jpaxjc.ns.persistence.orm.Embedded;
061    import net.sourceforge.jpaxjc.ns.persistence.orm.EmptyType;
062    import net.sourceforge.jpaxjc.ns.persistence.orm.Entity;
063    import net.sourceforge.jpaxjc.ns.persistence.orm.EntityListener;
064    import net.sourceforge.jpaxjc.ns.persistence.orm.EntityListeners;
065    import net.sourceforge.jpaxjc.ns.persistence.orm.EntityMappings;
066    import net.sourceforge.jpaxjc.ns.persistence.orm.EntityResult;
067    import net.sourceforge.jpaxjc.ns.persistence.orm.FieldResult;
068    import net.sourceforge.jpaxjc.ns.persistence.orm.GeneratedValue;
069    import net.sourceforge.jpaxjc.ns.persistence.orm.GenerationType;
070    import net.sourceforge.jpaxjc.ns.persistence.orm.Id;
071    import net.sourceforge.jpaxjc.ns.persistence.orm.IdClass;
072    import net.sourceforge.jpaxjc.ns.persistence.orm.Inheritance;
073    import net.sourceforge.jpaxjc.ns.persistence.orm.JoinColumn;
074    import net.sourceforge.jpaxjc.ns.persistence.orm.JoinTable;
075    import net.sourceforge.jpaxjc.ns.persistence.orm.ManyToMany;
076    import net.sourceforge.jpaxjc.ns.persistence.orm.ManyToOne;
077    import net.sourceforge.jpaxjc.ns.persistence.orm.MappedSuperclass;
078    import net.sourceforge.jpaxjc.ns.persistence.orm.NamedNativeQuery;
079    import net.sourceforge.jpaxjc.ns.persistence.orm.NamedQuery;
080    import net.sourceforge.jpaxjc.ns.persistence.orm.OneToMany;
081    import net.sourceforge.jpaxjc.ns.persistence.orm.OneToOne;
082    import net.sourceforge.jpaxjc.ns.persistence.orm.PersistenceUnitMetadata;
083    import net.sourceforge.jpaxjc.ns.persistence.orm.PostLoad;
084    import net.sourceforge.jpaxjc.ns.persistence.orm.PostPersist;
085    import net.sourceforge.jpaxjc.ns.persistence.orm.PostRemove;
086    import net.sourceforge.jpaxjc.ns.persistence.orm.PostUpdate;
087    import net.sourceforge.jpaxjc.ns.persistence.orm.PrePersist;
088    import net.sourceforge.jpaxjc.ns.persistence.orm.PreRemove;
089    import net.sourceforge.jpaxjc.ns.persistence.orm.PreUpdate;
090    import net.sourceforge.jpaxjc.ns.persistence.orm.PrimaryKeyJoinColumn;
091    import net.sourceforge.jpaxjc.ns.persistence.orm.QueryHint;
092    import net.sourceforge.jpaxjc.ns.persistence.orm.SecondaryTable;
093    import net.sourceforge.jpaxjc.ns.persistence.orm.SequenceGenerator;
094    import net.sourceforge.jpaxjc.ns.persistence.orm.SqlResultSetMapping;
095    import net.sourceforge.jpaxjc.ns.persistence.orm.Table;
096    import net.sourceforge.jpaxjc.ns.persistence.orm.TableGenerator;
097    import net.sourceforge.jpaxjc.ns.persistence.orm.TemporalType;
098    import net.sourceforge.jpaxjc.ns.persistence.orm.Transient;
099    import net.sourceforge.jpaxjc.ns.persistence.orm.UniqueConstraint;
100    import net.sourceforge.jpaxjc.ns.persistence.orm.Version;
101    import com.sun.tools.xjc.BadCommandLineException;
102    import com.sun.tools.xjc.Options;
103    import com.sun.tools.xjc.Plugin;
104    import com.sun.tools.xjc.model.CCustomizations;
105    import com.sun.tools.xjc.model.CEnumLeafInfo;
106    import com.sun.tools.xjc.model.CPluginCustomization;
107    import com.sun.tools.xjc.model.CPropertyInfo;
108    import com.sun.tools.xjc.model.CTypeInfo;
109    import com.sun.tools.xjc.outline.Aspect;
110    import com.sun.tools.xjc.outline.ClassOutline;
111    import com.sun.tools.xjc.outline.FieldOutline;
112    import com.sun.tools.xjc.outline.Outline;
113    import com.sun.tools.xjc.outline.PackageOutline;
114    import com.sun.xml.xsom.XSAttributeDecl;
115    import com.sun.xml.xsom.XSAttributeUse;
116    import com.sun.xml.xsom.XSComponent;
117    import com.sun.xml.xsom.XSElementDecl;
118    import com.sun.xml.xsom.XSFacet;
119    import com.sun.xml.xsom.XSParticle;
120    import com.sun.xml.xsom.XSSimpleType;
121    import java.io.File;
122    import java.io.IOException;
123    import java.math.BigDecimal;
124    import java.math.BigInteger;
125    import java.text.MessageFormat;
126    import java.util.Arrays;
127    import java.util.Calendar;
128    import java.util.Collection;
129    import java.util.GregorianCalendar;
130    import java.util.HashSet;
131    import java.util.Iterator;
132    import java.util.List;
133    import java.util.ResourceBundle;
134    import java.util.Set;
135    import java.util.logging.Level;
136    import javax.xml.XMLConstants;
137    import javax.xml.bind.JAXB;
138    import javax.xml.bind.JAXBContext;
139    import javax.xml.bind.JAXBException;
140    import javax.xml.bind.Marshaller;
141    import javax.xml.bind.annotation.XmlTransient;
142    import javax.xml.datatype.DatatypeConfigurationException;
143    import javax.xml.datatype.DatatypeFactory;
144    import javax.xml.datatype.XMLGregorianCalendar;
145    import javax.xml.transform.dom.DOMSource;
146    import javax.xml.validation.Schema;
147    import javax.xml.validation.SchemaFactory;
148    import org.xml.sax.ErrorHandler;
149    import org.xml.sax.SAXException;
150    import org.xml.sax.SAXParseException;
151    
152    /**
153     * JPA-XJC plugin implementation.
154     *
155     * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
156     * @version $Id: PluginImpl.java 101 2010-08-18 20:44:45Z schulte2005 $
157     */
158    public final class PluginImpl extends Plugin
159    {
160        // This class was written in about 2 hours. Don't expect any beauties!
161    
162        /** ORM version the plugin supports. */
163        private static final String ORM_VERSION = "1.0";
164    
165        /** Persistence version the plugin supports. */
166        private static final String PERSISTENCE_VERSION = "1.0";
167    
168        /** {@code http://java.sun.com/xml/ns/persistence} namespace URI. */
169        private static final String PERSISTENCE_NS = "http://java.sun.com/xml/ns/persistence";
170    
171        /** Default {@code http://java.sun.com/xml/ns/persistence} schema system id. */
172        private static final String DEFAULT_PERSISTENCE_SYSTEM_ID =
173            "http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd";
174    
175        /** {@code http://java.sun.com/xml/ns/persistence} classpath location. */
176        private static final String PERSISTENCE_SCHEMA_CLASSPATH_LOCATION =
177            "/net/sourceforge/jpaxjc/ns/persistence/persistence_1_0.xsd";
178    
179        /** {@code http://java.sun.com/xml/ns/persistence/orm} namespace URI. */
180        private static final String ORM_NS = "http://java.sun.com/xml/ns/persistence/orm";
181    
182        /** Default {@code http://java.sun.com/xml/ns/persistence/orm} schema system id. */
183        private static final String DEFAULT_ORM_SYSTEM_ID = "http://java.sun.com/xml/ns/persistence/orm_1_0.xsd";
184    
185        /** {@code http://java.sun.com/xml/ns/persistence/orm} classpath location. */
186        private static final String ORM_SCHEMA_CLASSPATH_LOCATION =
187            "/net/sourceforge/jpaxjc/ns/persistence/orm/orm_1_0.xsd";
188    
189        /** Prefix added to messages logged to the console. */
190        private static final String MESSAGE_PREFIX = "JPA-XJC";
191    
192        /** Constant for the {@code -jpa} option. */
193        private static final String JPA_OPTION_NAME = "-jpa";
194    
195        /** Constant for the {@code -persistenceSystemId} option. */
196        private static final String PERSISTENCE_SYSTEM_ID_OPTION_NAME = "-persistenceSystemId";
197    
198        /** Constant for the {@code -ormSystemId} option. */
199        private static final String ORM_SYSTEM_ID_OPTION_NAME = "-ormSystemId";
200    
201        /** The persistence unit name of the generated unit. */
202        private String persistenceUnitName;
203    
204        /** The persistence unit root of the generated unit. */
205        private File persistenceUnitRoot;
206    
207        /** Options passed to the plugin. */
208        private Options options;
209    
210        /** {@code http://java.sun.com/xml/ns/persistence} schema system id. */
211        private String persistenceSystemId = DEFAULT_PERSISTENCE_SYSTEM_ID;
212    
213        /** {@code http://java.sun.com/xml/ns/persistence/orm} schema system id. */
214        private String ormSystemId = DEFAULT_ORM_SYSTEM_ID;
215    
216        /** Set of mapped classes. */
217        private final Set<String> mappedClasses = new HashSet<String>();
218    
219        /** Empty JType array. */
220        private static final JType[] NO_JTYPES =
221        {
222        };
223    
224        // --
225        // Plugin methods.
226        // --
227        @Override
228        public String getOptionName()
229        {
230            return "jpa";
231        }
232    
233        @Override
234        public int parseArgument( final Options opt, final String[] args, int i )
235            throws BadCommandLineException, IOException
236        {
237            if ( JPA_OPTION_NAME.equals( args[i] ) )
238            {
239                this.persistenceUnitName = opt.requireArgument( JPA_OPTION_NAME, args, ++i );
240                this.persistenceUnitRoot = new File( opt.requireArgument( JPA_OPTION_NAME, args, ++i ) );
241                return 3;
242            }
243    
244            if ( PERSISTENCE_SYSTEM_ID_OPTION_NAME.equals( args[i] ) )
245            {
246                this.persistenceSystemId = opt.requireArgument( PERSISTENCE_SYSTEM_ID_OPTION_NAME, args, ++i );
247                return 2;
248            }
249    
250            if ( ORM_SYSTEM_ID_OPTION_NAME.equals( args[i] ) )
251            {
252                this.ormSystemId = opt.requireArgument( ORM_SYSTEM_ID_OPTION_NAME, args, ++i );
253                return 2;
254            }
255    
256            return 0;
257        }
258    
259        @Override
260        public String getUsage()
261        {
262            final String lineSeparator = System.getProperty( "line.separator" );
263            final StringBuilder b = new StringBuilder();
264    
265            b.append( "  -jpa               :  " ).append( getMessage( "usage" ) ).append( lineSeparator );
266            b.append( "                     :  " ).append( getMessage( "usageUnitName" ) ).append( lineSeparator );
267            b.append( "                     :  " ).append( getMessage( "usageUnitRoot" ) ).append( lineSeparator );
268            b.append( "                     :  " ).append( getMessage( "jpaSystemId", this.persistenceSystemId ) ).
269                append( lineSeparator );
270    
271            b.append( "                     :  " ).append( getMessage( "ormSystemId", this.ormSystemId ) );
272    
273            return b.toString();
274        }
275    
276        @Override
277        public List<String> getCustomizationURIs()
278        {
279            return Arrays.asList( new String[]
280                {
281                    ORM_NS, PERSISTENCE_NS
282                } );
283    
284        }
285    
286        @Override
287        public boolean isCustomizationTagName( final String nsUri, final String localName )
288        {
289            return nsUri.equals( ORM_NS ) || nsUri.equals( PERSISTENCE_NS );
290        }
291    
292        @Override
293        public boolean run( final Outline model, final Options options, final ErrorHandler errorHandler )
294            throws SAXException
295        {
296            boolean success = true;
297            this.options = options;
298    
299            this.log( Level.INFO, "title" );
300    
301            try
302            {
303                final EntityMappings orm = new EntityMappings();
304                orm.setVersion( ORM_VERSION );
305    
306                this.mappedClasses.clear();
307    
308                for ( ClassOutline c : model.getClasses() )
309                {
310                    this.toMappedSuperclass( model, c, orm );
311                }
312                for ( ClassOutline c : model.getClasses() )
313                {
314                    this.toEmbeddable( c, orm );
315                }
316                for ( ClassOutline c : model.getClasses() )
317                {
318                    this.toEntity( model, c, orm );
319                }
320    
321                this.customizeOrm( model.getModel().getCustomizations(), orm );
322                for ( PackageOutline p : model.getAllPackageContexts() )
323                {
324                    this.generateAdapterMethods( model.getCodeModel(), p );
325                }
326    
327                for ( Entity e : orm.getEntity() )
328                {
329                    if ( e.getAttributes() == null )
330                    {
331                        e.setAttributes( new Attributes() );
332                    }
333    
334                    this.addMandatoryAttributes( orm, e.getAttributes(), this.getClassOutline( model, e.getClazz() ) );
335                }
336    
337                final Persistence p = new Persistence();
338                final Persistence.PersistenceUnit u = new Persistence.PersistenceUnit();
339                u.setName( this.persistenceUnitName );
340                p.setVersion( PERSISTENCE_VERSION );
341                p.getPersistenceUnit().add( u );
342    
343                this.customizePersistenceUnit( model.getModel().getCustomizations(), u );
344    
345                for ( Entity e : orm.getEntity() )
346                {
347                    if ( !u.getClazz().contains( e.getClazz() ) )
348                    {
349                        u.getClazz().add( e.getClazz() );
350                    }
351                }
352                for ( Embeddable e : orm.getEmbeddable() )
353                {
354                    if ( !u.getClazz().contains( e.getClazz() ) )
355                    {
356                        u.getClazz().add( e.getClazz() );
357                    }
358                }
359                for ( MappedSuperclass m : orm.getMappedSuperclass() )
360                {
361                    if ( !u.getClazz().contains( m.getClazz() ) )
362                    {
363                        u.getClazz().add( m.getClazz() );
364                    }
365                }
366    
367                this.annotate( model, orm );
368                orm.getEmbeddable().clear();
369                orm.getEntity().clear();
370                orm.getMappedSuperclass().clear();
371    
372                final SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
373                final Schema persistenceSchema =
374                    schemaFactory.newSchema( this.getClass().getResource( PERSISTENCE_SCHEMA_CLASSPATH_LOCATION ) );
375    
376                final Schema ormSchema =
377                    schemaFactory.newSchema( this.getClass().getResource( ORM_SCHEMA_CLASSPATH_LOCATION ) );
378    
379                final JAXBContext persistenceCtx = JAXBContext.newInstance( "net.sourceforge.jpaxjc.ns.persistence" );
380                final JAXBContext ormCtx = JAXBContext.newInstance( "net.sourceforge.jpaxjc.ns.persistence.orm" );
381                final Marshaller persistenceMarshaller = persistenceCtx.createMarshaller();
382                final Marshaller ormMarshaller = ormCtx.createMarshaller();
383                persistenceMarshaller.setSchema( persistenceSchema );
384                persistenceMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
385                persistenceMarshaller.setProperty( Marshaller.JAXB_SCHEMA_LOCATION,
386                                                   PERSISTENCE_NS + ' ' + this.persistenceSystemId );
387    
388                ormMarshaller.setSchema( ormSchema );
389                ormMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
390                ormMarshaller.setProperty( Marshaller.JAXB_SCHEMA_LOCATION, ORM_NS + ' ' + this.ormSystemId );
391    
392                final File metaInf = new File( this.persistenceUnitRoot, "META-INF" );
393                if ( !metaInf.exists() )
394                {
395                    success = metaInf.mkdirs();
396                }
397    
398                if ( orm.getAccess() != null
399                     || orm.getCatalog() != null
400                     || orm.getDescription() != null
401                     || !orm.getNamedNativeQuery().isEmpty()
402                     || !orm.getNamedQuery().isEmpty()
403                     || orm.getPackage() != null
404                     || orm.getPersistenceUnitMetadata() != null
405                     || orm.getSchema() != null
406                     || !orm.getSequenceGenerator().isEmpty()
407                     || !orm.getSqlResultSetMapping().isEmpty()
408                     || !orm.getTableGenerator().isEmpty()
409                     || !orm.getEmbeddable().isEmpty()
410                     || !orm.getEntity().isEmpty()
411                     || !orm.getMappedSuperclass().isEmpty() )
412                {
413                    final File ormFile = new File( metaInf, this.persistenceUnitName + ".xml" );
414                    this.log( Level.INFO, "writing", ormFile.getAbsolutePath() );
415    
416                    ormMarshaller.marshal( orm, ormFile );
417                    u.getMappingFile().add( "META-INF/" + this.persistenceUnitName + ".xml" );
418                }
419    
420                final File persistenceFile = new File( metaInf, "persistence.xml" );
421                this.log( Level.INFO, "writing", persistenceFile.getAbsolutePath() );
422    
423                persistenceMarshaller.marshal( p, persistenceFile );
424            }
425            catch ( JAXBException e )
426            {
427                errorHandler.fatalError( new SAXParseException( e.getMessage(), null, e ) );
428                success = false;
429            }
430    
431            return success;
432        }
433    
434        // ---
435        // Mapping methods.
436        // ---
437        private void toMappedSuperclass( final Outline outline, final ClassOutline c, final EntityMappings orm )
438            throws JAXBException
439        {
440            if ( !this.mappedClasses.contains( c.implClass.binaryName() )
441                 && c.target.getCustomizations().find( ORM_NS, "mapped-superclass" ) != null )
442            {
443                final CPluginCustomization pc = c.target.getCustomizations().find( ORM_NS, "mapped-superclass" );
444                final MappedSuperclass mappedSuperclass =
445                    JAXB.unmarshal( new DOMSource( pc.element ), MappedSuperclass.class );
446    
447                orm.getMappedSuperclass().add( mappedSuperclass );
448                this.toMappedSuperclass( outline, c, orm, mappedSuperclass );
449    
450                if ( !pc.isAcknowledged() )
451                {
452                    pc.markAsAcknowledged();
453                }
454    
455                this.mappedClasses.add( mappedSuperclass.getClazz() );
456            }
457        }
458    
459        private void toEmbeddable( final ClassOutline c, final EntityMappings orm )
460            throws JAXBException
461        {
462            if ( !this.mappedClasses.contains( c.implClass.binaryName() )
463                 && c.target.getCustomizations().find( ORM_NS, "embeddable" ) != null )
464            {
465                final CPluginCustomization pc = c.target.getCustomizations().find( ORM_NS, "embeddable" );
466                final Embeddable embeddable = JAXB.unmarshal( new DOMSource( pc.element ), Embeddable.class );
467    
468                orm.getEmbeddable().add( embeddable );
469                this.toEmbeddable( c, embeddable );
470    
471                if ( !pc.isAcknowledged() )
472                {
473                    pc.markAsAcknowledged();
474                }
475    
476                this.mappedClasses.add( embeddable.getClazz() );
477            }
478        }
479    
480        private void toEntity( final Outline outline, final ClassOutline c, final EntityMappings orm )
481            throws JAXBException
482        {
483            if ( !this.mappedClasses.contains( c.implClass.binaryName() ) )
484            {
485                boolean mapped = false;
486    
487                Entity entity = null;
488                if ( c.target.getCustomizations().find( ORM_NS, "entity" ) != null )
489                {
490                    final CPluginCustomization pc = c.target.getCustomizations().find( ORM_NS, "entity" );
491                    entity = JAXB.unmarshal( new DOMSource( pc.element ), Entity.class );
492    
493                    orm.getEntity().add( entity );
494                    this.toEntity( outline, c, entity );
495    
496                    mapped = true;
497    
498                    if ( !pc.isAcknowledged() )
499                    {
500                        pc.markAsAcknowledged();
501                    }
502                }
503    
504                if ( !mapped )
505                {
506                    // Defaults to create an entity per class.
507                    entity = new Entity();
508                    String name = c.implClass.binaryName();
509                    entity.setClazz( name );
510    
511                    final String pkgName = c.implClass.getPackage().name();
512                    if ( pkgName != null && pkgName.length() > 0 )
513                    {
514                        name = name.substring( pkgName.length() + 1 );
515                    }
516    
517                    entity.setName( name );
518                    orm.getEntity().add( entity );
519                    this.toEntity( outline, c, entity );
520                    mapped = true;
521                }
522    
523                this.mappedClasses.add( entity.getClazz() );
524            }
525        }
526    
527        private void toEntity( final Outline outline, final ClassOutline c, final Entity entity )
528            throws JAXBException
529        {
530            if ( entity.getAccess() == null )
531            {
532                entity.setAccess( AccessType.PROPERTY );
533            }
534            if ( entity.getClazz() == null )
535            {
536                entity.setClazz( c.implClass.binaryName() );
537            }
538            if ( entity.getName() == null )
539            {
540                String name = c.implClass.binaryName();
541                String pkgName = c.implClass.getPackage().name();
542    
543                if ( pkgName != null && pkgName.length() > 0 )
544                {
545                    name = name.substring( pkgName.length() + 1 );
546                }
547    
548                entity.setName( name );
549            }
550            if ( entity.getAttributes() == null )
551            {
552                entity.setAttributes( new Attributes() );
553            }
554    
555            this.toAttributes( outline, c, entity.getAttributes() );
556    
557            this.customizeEntity( c.target.getCustomizations(), entity );
558        }
559    
560        private void toEmbeddable( final ClassOutline c, final Embeddable embeddable )
561            throws JAXBException
562        {
563            if ( embeddable.getAccess() == null )
564            {
565                embeddable.setAccess( AccessType.PROPERTY );
566            }
567            if ( embeddable.getClazz() == null )
568            {
569                embeddable.setClazz( c.implClass.binaryName() );
570            }
571            if ( embeddable.getAttributes() == null )
572            {
573                embeddable.setAttributes( new EmbeddableAttributes() );
574            }
575    
576            this.toEmbeddableAttributes( c, embeddable.getAttributes() );
577    
578            this.customizeEmbeddable( c.target.getCustomizations(), embeddable );
579        }
580    
581        private void toMappedSuperclass( final Outline outline, final ClassOutline c, final EntityMappings orm,
582                                         final MappedSuperclass mappedSuperclass )
583            throws JAXBException
584        {
585            if ( mappedSuperclass.getAccess() == null )
586            {
587                mappedSuperclass.setAccess( AccessType.PROPERTY );
588            }
589            if ( mappedSuperclass.getClazz() == null )
590            {
591                mappedSuperclass.setClazz( c.implClass.binaryName() );
592            }
593            if ( mappedSuperclass.getAttributes() == null )
594            {
595                mappedSuperclass.setAttributes( new Attributes() );
596            }
597    
598            this.toAttributes( outline, c, mappedSuperclass.getAttributes() );
599    
600            this.customizeMappedSuperclass( c.target.getCustomizations(), mappedSuperclass );
601        }
602    
603        private void toAttributes( final Outline outline, final ClassOutline c, final Attributes attributes )
604            throws JAXBException
605        {
606            if ( c.target.declaresAttributeWildcard() )
607            {
608                final Transient t = new Transient();
609                t.setName( "otherAttributes" );
610                attributes.getTransient().add( t );
611    
612                this.log( Level.WARNING, "cannotMapProperty", "OtherAttributes", c.implClass.binaryName() );
613            }
614    
615            for ( FieldOutline f : c.getDeclaredFields() )
616            {
617                boolean mapped = false;
618    
619                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "id" ) != null )
620                {
621                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "id" );
622                    final Id id = JAXB.unmarshal( new DOMSource( pc.element ), Id.class );
623    
624                    if ( id.getName() == null )
625                    {
626                        id.setName( f.getPropertyInfo().getName( false ) );
627                    }
628    
629                    attributes.getId().add( id );
630                    mapped = true;
631    
632                    final Column defaultColumn =
633                        this.applySchemaDefaults( f.getPropertyInfo().getSchemaComponent(), id.getColumn() );
634    
635                    id.setColumn( defaultColumn );
636    
637                    if ( !pc.isAcknowledged() )
638                    {
639                        pc.markAsAcknowledged();
640                    }
641                }
642    
643                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "basic" ) != null )
644                {
645                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "basic" );
646                    final Basic basic = JAXB.unmarshal( new DOMSource( pc.element ), Basic.class );
647    
648                    if ( basic.getName() == null )
649                    {
650                        basic.setName( f.getPropertyInfo().getName( false ) );
651                    }
652    
653                    attributes.getBasic().add( basic );
654                    mapped = true;
655    
656                    if ( !pc.isAcknowledged() )
657                    {
658                        pc.markAsAcknowledged();
659                    }
660    
661                    final Column defaultColumn =
662                        this.applySchemaDefaults( f.getPropertyInfo().getSchemaComponent(), basic.getColumn() );
663    
664                    basic.setColumn( defaultColumn );
665                }
666    
667                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "version" ) != null )
668                {
669                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "version" );
670                    final Version version = JAXB.unmarshal( new DOMSource( pc.element ), Version.class );
671    
672                    if ( version.getName() == null )
673                    {
674                        version.setName( f.getPropertyInfo().getName( false ) );
675                    }
676    
677                    attributes.getVersion().add( version );
678                    mapped = true;
679    
680                    if ( !pc.isAcknowledged() )
681                    {
682                        pc.markAsAcknowledged();
683                    }
684    
685                    final Column defaultColumn =
686                        this.applySchemaDefaults( f.getPropertyInfo().getSchemaComponent(), version.getColumn() );
687    
688                    version.setColumn( defaultColumn );
689                }
690    
691                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "many-to-one" ) != null )
692                {
693                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "many-to-one" );
694                    final ManyToOne m = JAXB.unmarshal( new DOMSource( pc.element ), ManyToOne.class );
695    
696                    if ( m.getName() == null )
697                    {
698                        m.setName( f.getPropertyInfo().getName( false ) );
699                    }
700    
701                    attributes.getManyToOne().add( m );
702                    mapped = true;
703    
704                    if ( !pc.isAcknowledged() )
705                    {
706                        pc.markAsAcknowledged();
707                    }
708                }
709    
710                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "one-to-many" ) != null )
711                {
712                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "one-to-many" );
713                    final OneToMany o = JAXB.unmarshal( new DOMSource( pc.element ), OneToMany.class );
714    
715                    if ( o.getName() == null )
716                    {
717                        o.setName( f.getPropertyInfo().getName( false ) );
718                    }
719    
720                    attributes.getOneToMany().add( o );
721    
722                    this.generateCollectionSetter( f.parent().parent().getCodeModel(), f.parent(), f.getPropertyInfo() );
723                    mapped = true;
724    
725                    if ( !pc.isAcknowledged() )
726                    {
727                        pc.markAsAcknowledged();
728                    }
729                }
730    
731                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "one-to-one" ) != null )
732                {
733                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "one-to-one" );
734                    final OneToOne o = JAXB.unmarshal( new DOMSource( pc.element ), OneToOne.class );
735    
736                    if ( o.getName() == null )
737                    {
738                        o.setName( f.getPropertyInfo().getName( false ) );
739                    }
740    
741                    attributes.getOneToOne().add( o );
742                    mapped = true;
743    
744                    if ( !pc.isAcknowledged() )
745                    {
746                        pc.markAsAcknowledged();
747                    }
748                }
749    
750                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "many-to-many" ) != null )
751                {
752                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "many-to-many" );
753                    final ManyToMany m = JAXB.unmarshal( new DOMSource( pc.element ), ManyToMany.class );
754    
755                    if ( m.getName() == null )
756                    {
757                        m.setName( f.getPropertyInfo().getName( false ) );
758                    }
759    
760                    attributes.getManyToMany().add( m );
761    
762                    this.generateCollectionSetter( f.parent().parent().getCodeModel(), f.parent(), f.getPropertyInfo() );
763                    mapped = true;
764    
765                    if ( !pc.isAcknowledged() )
766                    {
767                        pc.markAsAcknowledged();
768                    }
769                }
770    
771                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "embedded" ) != null )
772                {
773                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "embedded" );
774                    final Embedded e = JAXB.unmarshal( new DOMSource( pc.element ), Embedded.class );
775    
776                    if ( e.getName() == null )
777                    {
778                        e.setName( f.getPropertyInfo().getName( false ) );
779                    }
780    
781                    attributes.getEmbedded().add( e );
782                    mapped = true;
783    
784                    if ( !pc.isAcknowledged() )
785                    {
786                        pc.markAsAcknowledged();
787                    }
788                }
789    
790                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "transient" ) != null )
791                {
792                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "transient" );
793                    final Transient t = JAXB.unmarshal( new DOMSource( pc.element ), Transient.class );
794    
795                    if ( t.getName() == null )
796                    {
797                        t.setName( f.getPropertyInfo().getName( false ) );
798                    }
799    
800                    attributes.getTransient().add( t );
801                    mapped = true;
802    
803                    if ( !pc.isAcknowledged() )
804                    {
805                        pc.markAsAcknowledged();
806                    }
807                }
808    
809                if ( !mapped )
810                {
811                    this.toDefaultAttribute( outline, f, attributes );
812                }
813            }
814        }
815    
816        private void toEmbeddableAttributes( final ClassOutline c, final EmbeddableAttributes attributes )
817            throws JAXBException
818        {
819            if ( c.target.declaresAttributeWildcard() )
820            {
821                final Transient t = new Transient();
822                t.setName( "otherAttributes" );
823                attributes.getTransient().add( t );
824    
825                this.log( Level.WARNING, "cannotMapProperty", "OtherAttributes", c.implClass.binaryName() );
826            }
827    
828            for ( FieldOutline f : c.getDeclaredFields() )
829            {
830                boolean mapped = false;
831    
832                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "basic" ) != null )
833                {
834                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "basic" );
835                    final Basic basic = JAXB.unmarshal( new DOMSource( pc.element ), Basic.class );
836    
837                    if ( basic.getName() == null )
838                    {
839                        basic.setName( f.getPropertyInfo().getName( false ) );
840                    }
841    
842                    attributes.getBasic().add( basic );
843                    mapped = true;
844    
845                    if ( !pc.isAcknowledged() )
846                    {
847                        pc.markAsAcknowledged();
848                    }
849                }
850    
851                if ( f.getPropertyInfo().getCustomizations().find( ORM_NS, "transient" ) != null )
852                {
853                    final CPluginCustomization pc = f.getPropertyInfo().getCustomizations().find( ORM_NS, "transient" );
854                    final Transient t = JAXB.unmarshal( new DOMSource( pc.element ), Transient.class );
855    
856                    if ( t.getName() == null )
857                    {
858                        t.setName( f.getPropertyInfo().getName( false ) );
859                    }
860    
861                    attributes.getTransient().add( t );
862                    mapped = true;
863    
864                    if ( !pc.isAcknowledged() )
865                    {
866                        pc.markAsAcknowledged();
867                    }
868                }
869    
870                if ( !mapped )
871                {
872                    this.toDefaultAttribute( f, attributes );
873                }
874            }
875        }
876    
877        private boolean toDefaultAttribute( final Outline outline, final FieldOutline f, final Attributes a )
878        {
879            boolean mapped = false;
880    
881            if ( !mapped && this.isBasicFieldOutline( f ) )
882            {
883                final Basic basic = new Basic();
884                if ( f.getPropertyInfo().isOptionalPrimitive() )
885                {
886                    basic.setOptional( true );
887                }
888    
889                basic.setName( f.getPropertyInfo().getName( false ) );
890                basic.setColumn( this.toColumn( f.getPropertyInfo().getSchemaComponent() ) );
891                this.toTemporal( f, basic );
892                a.getBasic().add( basic );
893                mapped = true;
894            }
895    
896            if ( !mapped )
897            {
898                final Collection<? extends CTypeInfo> ref = f.getPropertyInfo().ref();
899    
900                if ( ref != null && ref.size() == 1 )
901                {
902                    final CTypeInfo refType = ref.iterator().next();
903                    final ClassOutline refClass =
904                        this.getClassOutline( outline, refType.toType( outline, Aspect.EXPOSED ).binaryName() );
905    
906                    if ( refClass != null )
907                    {
908                        if ( f.getPropertyInfo().isCollection() )
909                        {
910                            final OneToMany m = new OneToMany();
911                            m.setName( f.getPropertyInfo().getName( false ) );
912                            a.getOneToMany().add( m );
913    
914                            this.generateCollectionSetter( outline.getCodeModel(), f.parent(), f.getPropertyInfo() );
915                            mapped = true;
916                        }
917    
918                        if ( !mapped )
919                        {
920                            final OneToOne o = new OneToOne();
921                            o.setName( f.getPropertyInfo().getName( false ) );
922                            a.getOneToOne().add( o );
923    
924                            final Column col = this.toColumn( f.getPropertyInfo().getSchemaComponent() );
925                            o.setOptional( col != null && col.isNullable() );
926    
927                            mapped = true;
928                        }
929                    }
930                }
931            }
932    
933            if ( !mapped )
934            {
935                mapped = this.toTransient( f, a );
936            }
937    
938            return mapped;
939        }
940    
941        private boolean toDefaultAttribute( final FieldOutline f, final EmbeddableAttributes a )
942        {
943            boolean mapped = false;
944    
945            if ( !mapped && this.isBasicFieldOutline( f ) )
946            {
947                final Basic basic = new Basic();
948                if ( f.getPropertyInfo().isOptionalPrimitive() )
949                {
950                    basic.setOptional( true );
951                }
952    
953                basic.setName( f.getPropertyInfo().getName( false ) );
954                basic.setColumn( this.toColumn( f.getPropertyInfo().getSchemaComponent() ) );
955                this.toTemporal( f, basic );
956                a.getBasic().add( basic );
957                mapped = true;
958            }
959    
960            if ( !mapped )
961            {
962                mapped = this.toTransient( f, a );
963            }
964    
965            return mapped;
966        }
967    
968        private void toTemporal( final FieldOutline f, final Basic basic )
969        {
970            final String typeName = f.getRawType().binaryName();
971            final JCodeModel cm = f.parent().parent().getCodeModel();
972    
973            if ( typeName.equals( cm.ref( java.util.Date.class ).binaryName() )
974                 || typeName.equals( cm.ref( java.sql.Date.class ).binaryName() )
975                 || typeName.equals( cm.ref( Calendar.class ).binaryName() ) )
976            {
977                basic.setTemporal( TemporalType.DATE );
978            }
979            else if ( typeName.equals( cm.ref( java.sql.Time.class ).binaryName() ) )
980            {
981                basic.setTemporal( TemporalType.TIME );
982            }
983            else if ( typeName.equals( cm.ref( java.sql.Timestamp.class ).binaryName() ) )
984            {
985                basic.setTemporal( TemporalType.TIMESTAMP );
986            }
987        }
988    
989        private void addMandatoryAttributes( final EntityMappings orm, final Attributes a, final ClassOutline c )
990        {
991            class RecursionHelper
992            {
993    
994                void recurseAddId( final EntityMappings orm, final Attributes a, final ClassOutline c )
995                {
996                    if ( a.getId().isEmpty() )
997                    {
998                        if ( c.getSuperClass() != null )
999                        {
1000                            final Attributes attr = getAttributes( orm, c.getSuperClass().implClass.binaryName() );
1001                            recurseAddId( orm, attr, c.getSuperClass() );
1002                        }
1003                        else
1004                        {
1005                            final Id id = new Id();
1006                            final GeneratedValue gv = new GeneratedValue();
1007                            final Column col = new Column();
1008                            a.getId().add( id );
1009    
1010                            gv.setStrategy( GenerationType.AUTO );
1011                            col.setScale( 0 );
1012                            col.setPrecision( 20 );
1013                            col.setNullable( false );
1014                            id.setName( "jpaId" );
1015                            id.setGeneratedValue( gv );
1016                            id.setColumn( col );
1017    
1018                            generateProperty( id.getName(), Long.TYPE, c );
1019                        }
1020                    }
1021                }
1022    
1023                void recurseAddVersion( final EntityMappings orm, final Attributes a, final ClassOutline c )
1024                {
1025                    if ( a.getVersion().isEmpty() )
1026                    {
1027                        if ( c.getSuperClass() != null )
1028                        {
1029                            final Attributes attr = getAttributes( orm, c.getSuperClass().implClass.binaryName() );
1030                            if ( attr != null )
1031                            {
1032                                this.recurseAddVersion( orm, attr, c.getSuperClass() );
1033                            }
1034                        }
1035                        else
1036                        {
1037                            final Version v = new Version();
1038                            final Column col = new Column();
1039                            a.getVersion().add( v );
1040    
1041                            col.setScale( 0 );
1042                            col.setPrecision( 20 );
1043                            col.setNullable( false );
1044                            v.setName( "jpaVersion" );
1045                            v.setColumn( col );
1046    
1047                            generateProperty( v.getName(), Long.TYPE, c );
1048                        }
1049                    }
1050                }
1051    
1052            }
1053    
1054            final RecursionHelper rh = new RecursionHelper();
1055            rh.recurseAddId( orm, a, c );
1056            rh.recurseAddVersion( orm, a, c );
1057        }
1058    
1059        private boolean toTransient( final FieldOutline f, final Attributes a )
1060        {
1061            final Transient t = new Transient();
1062            t.setName( f.getPropertyInfo().getName( false ) );
1063            a.getTransient().add( t );
1064    
1065            if ( f.getRawType().equals( f.parent().parent().getCodeModel().ref( XMLGregorianCalendar.class ) ) )
1066            {
1067                a.getBasic().add( this.toTemporalBasic( f ) );
1068            }
1069            else
1070            {
1071                this.log( Level.WARNING, "cannotMapProperty", f.getPropertyInfo().getName( true ),
1072                          f.parent().implClass.binaryName() );
1073    
1074            }
1075    
1076            return true;
1077        }
1078    
1079        private boolean toTransient( final FieldOutline f, final EmbeddableAttributes a )
1080        {
1081            final Transient t = new Transient();
1082            t.setName( f.getPropertyInfo().getName( false ) );
1083            a.getTransient().add( t );
1084    
1085            if ( f.getRawType().equals( f.parent().parent().getCodeModel().ref( XMLGregorianCalendar.class ) ) )
1086            {
1087                a.getBasic().add( this.toTemporalBasic( f ) );
1088            }
1089            else
1090            {
1091                this.log( Level.WARNING, "cannotMapProperty", f.getPropertyInfo().getName( true ),
1092                          f.parent().implClass.binaryName() );
1093    
1094            }
1095    
1096            return true;
1097        }
1098    
1099        private Basic toTemporalBasic( final FieldOutline f )
1100        {
1101            final Basic b = new Basic();
1102            b.setName( "jpa" + f.getPropertyInfo().getName( true ) );
1103            b.setTemporal( TemporalType.TIMESTAMP );
1104    
1105            this.generateTemporalBasic( f );
1106    
1107            return b;
1108        }
1109    
1110        private Column toColumn( final XSComponent xs )
1111        {
1112            Column col = null;
1113            boolean columnEmpty = true;
1114    
1115            XSSimpleType type = null;
1116            if ( xs instanceof XSParticle )
1117            {
1118                col = new Column();
1119                col.setNullable( ( (XSParticle) xs ).getMinOccurs() == 0 );
1120                columnEmpty = false;
1121            }
1122            else if ( xs instanceof XSSimpleType )
1123            {
1124                col = new Column();
1125                type = (XSSimpleType) xs;
1126            }
1127            else if ( xs instanceof XSAttributeDecl )
1128            {
1129                col = new Column();
1130                type = ( (XSAttributeDecl) xs ).getType();
1131            }
1132            else if ( xs instanceof XSAttributeUse )
1133            {
1134                final XSAttributeUse au = (XSAttributeUse) xs;
1135                col = new Column();
1136                col.setNullable( !au.isRequired() );
1137                columnEmpty = false;
1138                type = ( (XSAttributeUse) xs ).getDecl().getType();
1139            }
1140            else if ( xs instanceof XSElementDecl )
1141            {
1142                col = new Column();
1143                final XSElementDecl decl = (XSElementDecl) xs;
1144                col.setNullable( decl.isNillable() );
1145                columnEmpty = false;
1146                type = ( (XSElementDecl) xs ).getType().asSimpleType();
1147            }
1148    
1149            if ( type != null )
1150            {
1151                final XSFacet length = type.getFacet( XSFacet.FACET_LENGTH );
1152                final XSFacet maxLength = type.getFacet( XSFacet.FACET_MAXLENGTH );
1153                final XSFacet fractionDigits = type.getFacet( XSFacet.FACET_FRACTIONDIGITS );
1154                final XSFacet totalDigits = type.getFacet( XSFacet.FACET_TOTALDIGITS );
1155    
1156                if ( length != null )
1157                {
1158                    col.setLength( new Integer( length.getValue().value ) );
1159                    columnEmpty = false;
1160                }
1161                else if ( maxLength != null )
1162                {
1163                    col.setLength( new Integer( maxLength.getValue().value ) );
1164                    columnEmpty = false;
1165                }
1166    
1167                if ( fractionDigits != null )
1168                {
1169                    col.setScale( new Integer( fractionDigits.getValue().value ) );
1170                    columnEmpty = false;
1171                }
1172                if ( totalDigits != null )
1173                {
1174                    col.setPrecision( new Integer( totalDigits.getValue().value ) );
1175                    columnEmpty = false;
1176                }
1177    
1178                if ( this.getSchemaSimpleType( type, "decimal" ) != null
1179                     && ( col.getScale() == null || col.getPrecision() == null ) )
1180                {
1181                    XSSimpleType schemaType = this.getSchemaSimpleType( type, "integer" );
1182                    if ( schemaType != null && col.getScale() == null )
1183                    {
1184                        col.setScale( new Integer( 0 ) );
1185                        columnEmpty = false;
1186                    }
1187    
1188                    if ( col.getPrecision() == null )
1189                    {
1190                        schemaType = this.getSchemaSimpleType( type, "long" );
1191                        if ( schemaType != null )
1192                        {
1193                            col.setPrecision( new Integer( 20 ) );
1194                            columnEmpty = false;
1195                        }
1196                        schemaType = this.getSchemaSimpleType( type, "int" );
1197                        if ( schemaType != null )
1198                        {
1199                            col.setPrecision( new Integer( 10 ) );
1200                            columnEmpty = false;
1201                        }
1202                        schemaType = this.getSchemaSimpleType( type, "short" );
1203                        if ( schemaType != null )
1204                        {
1205                            col.setPrecision( new Integer( 5 ) );
1206                            columnEmpty = false;
1207                        }
1208                        schemaType = this.getSchemaSimpleType( type, "byte" );
1209                        if ( schemaType != null )
1210                        {
1211                            col.setPrecision( new Integer( 3 ) );
1212                            columnEmpty = false;
1213                        }
1214                        schemaType = this.getSchemaSimpleType( type, "unsignedLong" );
1215                        if ( schemaType != null )
1216                        {
1217                            col.setPrecision( new Integer( 20 ) );
1218                            columnEmpty = false;
1219                        }
1220                        schemaType = this.getSchemaSimpleType( type, "unsignedInt" );
1221                        if ( schemaType != null )
1222                        {
1223                            col.setPrecision( new Integer( 10 ) );
1224                            columnEmpty = false;
1225                        }
1226                        schemaType = this.getSchemaSimpleType( type, "unsignedShort" );
1227                        if ( schemaType != null )
1228                        {
1229                            col.setPrecision( new Integer( 5 ) );
1230                            columnEmpty = false;
1231                        }
1232                        schemaType = this.getSchemaSimpleType( type, "unsignedByte" );
1233                        if ( schemaType != null )
1234                        {
1235                            col.setPrecision( new Integer( 3 ) );
1236                            columnEmpty = false;
1237                        }
1238                    }
1239                }
1240            }
1241    
1242            return columnEmpty ? null : col;
1243        }
1244    
1245        private Column applySchemaDefaults( final XSComponent comp, final Column column )
1246        {
1247            final Column defaultColumn = this.toColumn( comp );
1248            if ( defaultColumn != null )
1249            {
1250                if ( column == null )
1251                {
1252                    return defaultColumn;
1253                }
1254    
1255                if ( column.isInsertable() == null )
1256                {
1257                    column.setInsertable( defaultColumn.isInsertable() );
1258                }
1259                if ( column.isNullable() == null )
1260                {
1261                    column.setNullable( defaultColumn.isNullable() );
1262                }
1263                if ( column.isUnique() == null )
1264                {
1265                    column.setUnique( defaultColumn.isUnique() );
1266                }
1267                if ( column.isUpdatable() == null )
1268                {
1269                    column.setUpdatable( defaultColumn.isUpdatable() );
1270                }
1271                if ( column.getColumnDefinition() == null )
1272                {
1273                    column.setColumnDefinition( defaultColumn.getColumnDefinition() );
1274                }
1275                if ( column.getLength() == null )
1276                {
1277                    column.setLength( defaultColumn.getLength() );
1278                }
1279                if ( column.getName() == null )
1280                {
1281                    column.setName( defaultColumn.getName() );
1282                }
1283                if ( column.getPrecision() == null )
1284                {
1285                    column.setPrecision( defaultColumn.getPrecision() );
1286                }
1287                if ( column.getScale() == null )
1288                {
1289                    column.setScale( defaultColumn.getScale() );
1290                }
1291                if ( column.getTable() == null )
1292                {
1293                    column.setTable( defaultColumn.getTable() );
1294                }
1295            }
1296    
1297            return column;
1298        }
1299    
1300        // --
1301        // Customization methods.
1302        // --
1303        private void customizeOrm( final CCustomizations customizations, final EntityMappings orm )
1304        {
1305            for ( CPluginCustomization c : customizations )
1306            {
1307                if ( c.element != null && c.element.getNamespaceURI().equals( ORM_NS ) )
1308                {
1309                    boolean acknowledge = false;
1310    
1311                    if ( c.element.getLocalName().equals( "description" ) )
1312                    {
1313                        orm.setDescription( c.element.getFirstChild().getNodeValue() );
1314                        acknowledge = true;
1315                    }
1316                    else if ( c.element.getLocalName().equals( "persistence-unit-metadata" ) )
1317                    {
1318                        final PersistenceUnitMetadata e =
1319                            JAXB.unmarshal( new DOMSource( c.element ), PersistenceUnitMetadata.class );
1320    
1321                        orm.setPersistenceUnitMetadata( e );
1322                        acknowledge = true;
1323                    }
1324                    else if ( c.element.getLocalName().equals( "package" ) )
1325                    {
1326                        orm.setPackage( c.element.getFirstChild().getNodeValue() );
1327                        acknowledge = true;
1328                    }
1329                    else if ( c.element.getLocalName().equals( "schema" ) )
1330                    {
1331                        orm.setSchema( c.element.getFirstChild().getNodeValue() );
1332                        acknowledge = true;
1333                    }
1334                    else if ( c.element.getLocalName().equals( "catalog" ) )
1335                    {
1336                        orm.setCatalog( c.element.getFirstChild().getNodeValue() );
1337                        acknowledge = true;
1338                    }
1339                    else if ( c.element.getLocalName().equals( "access" ) )
1340                    {
1341                        final AccessType e = JAXB.unmarshal( new DOMSource( c.element ), AccessType.class );
1342                        orm.setAccess( e );
1343                        acknowledge = true;
1344                    }
1345                    else if ( c.element.getLocalName().equals( "sequence-generator" ) )
1346                    {
1347                        final SequenceGenerator e = JAXB.unmarshal( new DOMSource( c.element ), SequenceGenerator.class );
1348                        orm.getSequenceGenerator().add( e );
1349                        acknowledge = true;
1350                    }
1351                    else if ( c.element.getLocalName().equals( "table-generator" ) )
1352                    {
1353                        final TableGenerator e = JAXB.unmarshal( new DOMSource( c.element ), TableGenerator.class );
1354                        orm.getTableGenerator().add( e );
1355                        acknowledge = true;
1356                    }
1357                    else if ( c.element.getLocalName().equals( "named-query" ) )
1358                    {
1359                        final NamedQuery e = JAXB.unmarshal( new DOMSource( c.element ), NamedQuery.class );
1360                        orm.getNamedQuery().add( e );
1361                        acknowledge = true;
1362                    }
1363                    else if ( c.element.getLocalName().equals( "named-native-query" ) )
1364                    {
1365                        final NamedNativeQuery e = JAXB.unmarshal( new DOMSource( c.element ), NamedNativeQuery.class );
1366                        orm.getNamedNativeQuery().add( e );
1367                        acknowledge = true;
1368                    }
1369                    else if ( c.element.getLocalName().equals( "sql-result-set-mapping" ) )
1370                    {
1371                        final SqlResultSetMapping e =
1372                            JAXB.unmarshal( new DOMSource( c.element ), SqlResultSetMapping.class );
1373    
1374                        orm.getSqlResultSetMapping().add( e );
1375                        acknowledge = true;
1376                    }
1377                    else if ( c.element.getLocalName().equals( "mapped-superclass" ) )
1378                    {
1379                        final MappedSuperclass e = JAXB.unmarshal( new DOMSource( c.element ), MappedSuperclass.class );
1380                        orm.getMappedSuperclass().add( e );
1381                        acknowledge = true;
1382                    }
1383                    else if ( c.element.getLocalName().equals( "entity" ) )
1384                    {
1385                        final Entity e = JAXB.unmarshal( new DOMSource( c.element ), Entity.class );
1386                        orm.getEntity().add( e );
1387                        acknowledge = true;
1388                    }
1389                    else if ( c.element.getLocalName().equals( "embeddable" ) )
1390                    {
1391                        final Embeddable e = JAXB.unmarshal( new DOMSource( c.element ), Embeddable.class );
1392                        orm.getEmbeddable().add( e );
1393                        acknowledge = true;
1394                    }
1395    
1396                    if ( acknowledge && !c.isAcknowledged() )
1397                    {
1398                        c.markAsAcknowledged();
1399                    }
1400                }
1401            }
1402        }
1403    
1404        private void customizeEntity( final CCustomizations customizations, final Entity entity )
1405        {
1406            for ( CPluginCustomization c : customizations )
1407            {
1408                if ( c.element != null && c.element.getNamespaceURI().equals( ORM_NS ) )
1409                {
1410                    boolean acknowledge = false;
1411    
1412                    if ( c.element.getLocalName().equals( "description" ) )
1413                    {
1414                        entity.setDescription( c.element.getFirstChild().getNodeValue() );
1415                        acknowledge = true;
1416                    }
1417                    else if ( c.element.getLocalName().equals( "table" ) )
1418                    {
1419                        final Table e = JAXB.unmarshal( new DOMSource( c.element ), Table.class );
1420                        entity.setTable( e );
1421                        acknowledge = true;
1422                    }
1423                    else if ( c.element.getLocalName().equals( "secondary-table" ) )
1424                    {
1425                        final SecondaryTable e = JAXB.unmarshal( new DOMSource( c.element ), SecondaryTable.class );
1426                        entity.getSecondaryTable().add( e );
1427                        acknowledge = true;
1428                    }
1429                    else if ( c.element.getLocalName().equals( "primary-key-join-column" ) )
1430                    {
1431                        final PrimaryKeyJoinColumn e =
1432                            JAXB.unmarshal( new DOMSource( c.element ), PrimaryKeyJoinColumn.class );
1433    
1434                        entity.getPrimaryKeyJoinColumn().add( e );
1435                        acknowledge = true;
1436                    }
1437                    else if ( c.element.getLocalName().equals( "id-class" ) )
1438                    {
1439                        final IdClass e = JAXB.unmarshal( new DOMSource( c.element ), IdClass.class );
1440                        entity.setIdClass( e );
1441                        acknowledge = true;
1442                    }
1443                    else if ( c.element.getLocalName().equals( "inheritance" ) )
1444                    {
1445                        final Inheritance e = JAXB.unmarshal( new DOMSource( c.element ), Inheritance.class );
1446                        entity.setInheritance( e );
1447                        acknowledge = true;
1448                    }
1449                    else if ( c.element.getLocalName().equals( "discriminator-value" ) )
1450                    {
1451                        entity.setDiscriminatorValue( c.element.getFirstChild().getNodeValue() );
1452                        acknowledge = true;
1453                    }
1454                    else if ( c.element.getLocalName().equals( "discriminator-column" ) )
1455                    {
1456                        final DiscriminatorColumn e =
1457                            JAXB.unmarshal( new DOMSource( c.element ), DiscriminatorColumn.class );
1458    
1459                        entity.setDiscriminatorColumn( e );
1460                        acknowledge = true;
1461                    }
1462                    else if ( c.element.getLocalName().equals( "sequence-generator" ) )
1463                    {
1464                        final SequenceGenerator e = JAXB.unmarshal( new DOMSource( c.element ), SequenceGenerator.class );
1465                        entity.setSequenceGenerator( e );
1466                        acknowledge = true;
1467                    }
1468                    else if ( c.element.getLocalName().equals( "table-generator" ) )
1469                    {
1470                        final TableGenerator e = JAXB.unmarshal( new DOMSource( c.element ), TableGenerator.class );
1471                        entity.setTableGenerator( e );
1472                        acknowledge = true;
1473                    }
1474                    else if ( c.element.getLocalName().equals( "named-query" ) )
1475                    {
1476                        final NamedQuery e = JAXB.unmarshal( new DOMSource( c.element ), NamedQuery.class );
1477                        entity.getNamedQuery().add( e );
1478                        acknowledge = true;
1479                    }
1480                    else if ( c.element.getLocalName().equals( "named-native-query" ) )
1481                    {
1482                        final NamedNativeQuery e = JAXB.unmarshal( new DOMSource( c.element ), NamedNativeQuery.class );
1483                        entity.getNamedNativeQuery().add( e );
1484                        acknowledge = true;
1485                    }
1486                    else if ( c.element.getLocalName().equals( "sql-result-set-mapping" ) )
1487                    {
1488                        final SqlResultSetMapping e =
1489                            JAXB.unmarshal( new DOMSource( c.element ), SqlResultSetMapping.class );
1490    
1491                        entity.getSqlResultSetMapping().add( e );
1492                        acknowledge = true;
1493                    }
1494                    else if ( c.element.getLocalName().equals( "exclude-default-listeners" ) )
1495                    {
1496                        final EmptyType e = JAXB.unmarshal( new DOMSource( c.element ), EmptyType.class );
1497                        entity.setExcludeDefaultListeners( e );
1498                        acknowledge = true;
1499                    }
1500                    else if ( c.element.getLocalName().equals( "exclude-superclass-listeners" ) )
1501                    {
1502                        final EmptyType e = JAXB.unmarshal( new DOMSource( c.element ), EmptyType.class );
1503                        entity.setExcludeSuperclassListeners( e );
1504                        acknowledge = true;
1505                    }
1506                    else if ( c.element.getLocalName().equals( "entity-listeners" ) )
1507                    {
1508                        final EntityListeners e = JAXB.unmarshal( new DOMSource( c.element ), EntityListeners.class );
1509                        entity.setEntityListeners( e );
1510                        acknowledge = true;
1511                    }
1512                    else if ( c.element.getLocalName().equals( "pre-persist" ) )
1513                    {
1514                        final PrePersist e = JAXB.unmarshal( new DOMSource( c.element ), PrePersist.class );
1515                        entity.setPrePersist( e );
1516                        acknowledge = true;
1517                    }
1518                    else if ( c.element.getLocalName().equals( "post-persist" ) )
1519                    {
1520                        final PostPersist e = JAXB.unmarshal( new DOMSource( c.element ), PostPersist.class );
1521                        entity.setPostPersist( e );
1522                        acknowledge = true;
1523                    }
1524                    else if ( c.element.getLocalName().equals( "pre-remove" ) )
1525                    {
1526                        final PreRemove e = JAXB.unmarshal( new DOMSource( c.element ), PreRemove.class );
1527                        entity.setPreRemove( e );
1528                        acknowledge = true;
1529                    }
1530                    else if ( c.element.getLocalName().equals( "post-remove" ) )
1531                    {
1532                        final PostRemove e = JAXB.unmarshal( new DOMSource( c.element ), PostRemove.class );
1533                        entity.setPostRemove( e );
1534                        acknowledge = true;
1535                    }
1536                    else if ( c.element.getLocalName().equals( "pre-update" ) )
1537                    {
1538                        final PreUpdate e = JAXB.unmarshal( new DOMSource( c.element ), PreUpdate.class );
1539                        entity.setPreUpdate( e );
1540                        acknowledge = true;
1541                    }
1542                    else if ( c.element.getLocalName().equals( "post-update" ) )
1543                    {
1544                        final PostUpdate e = JAXB.unmarshal( new DOMSource( c.element ), PostUpdate.class );
1545                        entity.setPostUpdate( e );
1546                        acknowledge = true;
1547                    }
1548                    else if ( c.element.getLocalName().equals( "post-load" ) )
1549                    {
1550                        final PostLoad e = JAXB.unmarshal( new DOMSource( c.element ), PostLoad.class );
1551                        entity.setPostLoad( e );
1552                        acknowledge = true;
1553                    }
1554                    else if ( c.element.getLocalName().equals( "attribute-override" ) )
1555                    {
1556                        final AttributeOverride e = JAXB.unmarshal( new DOMSource( c.element ), AttributeOverride.class );
1557                        entity.getAttributeOverride().add( e );
1558                        acknowledge = true;
1559                    }
1560                    else if ( c.element.getLocalName().equals( "attributes" ) )
1561                    {
1562                        final Attributes e = JAXB.unmarshal( new DOMSource( c.element ), Attributes.class );
1563                        entity.setAttributes( e );
1564                        acknowledge = true;
1565                    }
1566    
1567                    if ( acknowledge && !c.isAcknowledged() )
1568                    {
1569                        c.markAsAcknowledged();
1570                    }
1571                }
1572            }
1573        }
1574    
1575        private void customizeEmbeddable( final CCustomizations customizations, final Embeddable embeddable )
1576        {
1577            for ( CPluginCustomization c : customizations )
1578            {
1579                if ( c.element != null && c.element.getNamespaceURI().equals( ORM_NS ) )
1580                {
1581                    boolean acknowledge = false;
1582    
1583                    if ( c.element.getLocalName().equals( "description" ) )
1584                    {
1585                        embeddable.setDescription( c.element.getFirstChild().getNodeValue() );
1586                        acknowledge = true;
1587                    }
1588                    else if ( c.element.getLocalName().equals( "attributes" ) )
1589                    {
1590                        final EmbeddableAttributes e =
1591                            JAXB.unmarshal( new DOMSource( c.element ), EmbeddableAttributes.class );
1592    
1593                        embeddable.setAttributes( e );
1594                        acknowledge = true;
1595                    }
1596    
1597                    if ( acknowledge && !c.isAcknowledged() )
1598                    {
1599                        c.markAsAcknowledged();
1600                    }
1601                }
1602            }
1603        }
1604    
1605        private void customizeMappedSuperclass( final CCustomizations customizations, final MappedSuperclass ms )
1606        {
1607            for ( CPluginCustomization c : customizations )
1608            {
1609                if ( c.element != null && c.element.getNamespaceURI().equals( ORM_NS ) )
1610                {
1611                    boolean acknowledge = false;
1612    
1613                    if ( c.element.getLocalName().equals( "description" ) )
1614                    {
1615                        ms.setDescription( c.element.getFirstChild().getNodeValue() );
1616                        acknowledge = true;
1617                    }
1618                    else if ( c.element.getLocalName().equals( "id-class" ) )
1619                    {
1620                        final IdClass e = JAXB.unmarshal( new DOMSource( c.element ), IdClass.class );
1621                        ms.setIdClass( e );
1622                        acknowledge = true;
1623                    }
1624                    else if ( c.element.getLocalName().equals( "exclude-default-listeners" ) )
1625                    {
1626                        final EmptyType e = JAXB.unmarshal( new DOMSource( c.element ), EmptyType.class );
1627                        ms.setExcludeDefaultListeners( e );
1628                        acknowledge = true;
1629                    }
1630                    else if ( c.element.getLocalName().equals( "exclude-superclass-listeners" ) )
1631                    {
1632                        final EmptyType e = JAXB.unmarshal( new DOMSource( c.element ), EmptyType.class );
1633                        ms.setExcludeSuperclassListeners( e );
1634                        acknowledge = true;
1635                    }
1636                    else if ( c.element.getLocalName().equals( "entity-listeners" ) )
1637                    {
1638                        final EntityListeners e = JAXB.unmarshal( new DOMSource( c.element ), EntityListeners.class );
1639                        ms.setEntityListeners( e );
1640                        acknowledge = true;
1641                    }
1642                    else if ( c.element.getLocalName().equals( "pre-persist" ) )
1643                    {
1644                        final PrePersist e = JAXB.unmarshal( new DOMSource( c.element ), PrePersist.class );
1645                        ms.setPrePersist( e );
1646                        acknowledge = true;
1647                    }
1648                    else if ( c.element.getLocalName().equals( "post-persist" ) )
1649                    {
1650                        final PostPersist e = JAXB.unmarshal( new DOMSource( c.element ), PostPersist.class );
1651                        ms.setPostPersist( e );
1652                        acknowledge = true;
1653                    }
1654                    else if ( c.element.getLocalName().equals( "pre-remove" ) )
1655                    {
1656                        final PreRemove e = JAXB.unmarshal( new DOMSource( c.element ), PreRemove.class );
1657                        ms.setPreRemove( e );
1658                        acknowledge = true;
1659                    }
1660                    else if ( c.element.getLocalName().equals( "post-remove" ) )
1661                    {
1662                        final PostRemove e = JAXB.unmarshal( new DOMSource( c.element ), PostRemove.class );
1663                        ms.setPostRemove( e );
1664                        acknowledge = true;
1665                    }
1666                    else if ( c.element.getLocalName().equals( "pre-update" ) )
1667                    {
1668                        final PreUpdate e = JAXB.unmarshal( new DOMSource( c.element ), PreUpdate.class );
1669                        ms.setPreUpdate( e );
1670                        acknowledge = true;
1671                    }
1672                    else if ( c.element.getLocalName().equals( "post-update" ) )
1673                    {
1674                        final PostUpdate e = JAXB.unmarshal( new DOMSource( c.element ), PostUpdate.class );
1675                        ms.setPostUpdate( e );
1676                        acknowledge = true;
1677                    }
1678                    else if ( c.element.getLocalName().equals( "post-load" ) )
1679                    {
1680                        final PostLoad e = JAXB.unmarshal( new DOMSource( c.element ), PostLoad.class );
1681                        ms.setPostLoad( e );
1682                        acknowledge = true;
1683                    }
1684                    else if ( c.element.getLocalName().equals( "attributes" ) )
1685                    {
1686                        final Attributes e = JAXB.unmarshal( new DOMSource( c.element ), Attributes.class );
1687                        ms.setAttributes( e );
1688                        acknowledge = true;
1689                    }
1690    
1691                    if ( acknowledge && !c.isAcknowledged() )
1692                    {
1693                        c.markAsAcknowledged();
1694                    }
1695                }
1696            }
1697        }
1698    
1699        private void customizePersistenceUnit(
1700            final CCustomizations customizations, final Persistence.PersistenceUnit unit )
1701        {
1702            for ( CPluginCustomization c : customizations )
1703            {
1704                if ( c.element != null && c.element.getNamespaceURI().equals( PERSISTENCE_NS ) )
1705                {
1706                    boolean acknowledge = false;
1707    
1708                    if ( c.element.getLocalName().equals( "description" ) )
1709                    {
1710                        unit.setDescription( c.element.getFirstChild().getNodeValue() );
1711                        acknowledge = true;
1712                    }
1713                    else if ( c.element.getLocalName().equals( "provider" ) )
1714                    {
1715                        unit.setProvider( c.element.getFirstChild().getNodeValue() );
1716                        acknowledge = true;
1717                    }
1718                    else if ( c.element.getLocalName().equals( "jta-data-source" ) )
1719                    {
1720                        unit.setJtaDataSource( c.element.getFirstChild().getNodeValue() );
1721                        acknowledge = true;
1722                    }
1723                    else if ( c.element.getLocalName().equals( "non-jta-data-source" ) )
1724                    {
1725                        unit.setNonJtaDataSource( c.element.getFirstChild().getNodeValue() );
1726                        acknowledge = true;
1727                    }
1728                    else if ( c.element.getLocalName().equals( "mapping-file" ) )
1729                    {
1730                        unit.getMappingFile().add( c.element.getFirstChild().getNodeValue() );
1731                        acknowledge = true;
1732                    }
1733                    else if ( c.element.getLocalName().equals( "jar-file" ) )
1734                    {
1735                        unit.getJarFile().add( c.element.getFirstChild().getNodeValue() );
1736                        acknowledge = true;
1737                    }
1738                    else if ( c.element.getLocalName().equals( "class" ) )
1739                    {
1740                        unit.getClazz().add( c.element.getFirstChild().getNodeValue() );
1741                        acknowledge = true;
1742                    }
1743                    else if ( c.element.getLocalName().equals( "exclude-unlisted-classes" ) )
1744                    {
1745                        unit.setExcludeUnlistedClasses( Boolean.valueOf( c.element.getFirstChild().getNodeValue() ) );
1746                        acknowledge = true;
1747                    }
1748                    else if ( c.element.getLocalName().equals( "properties" ) )
1749                    {
1750                        final Persistence.PersistenceUnit.Properties e =
1751                            JAXB.unmarshal( new DOMSource( c.element ), Persistence.PersistenceUnit.Properties.class );
1752    
1753                        unit.setProperties( e );
1754                        acknowledge = true;
1755                    }
1756    
1757                    if ( acknowledge && !c.isAcknowledged() )
1758                    {
1759                        c.markAsAcknowledged();
1760                    }
1761                }
1762            }
1763        }
1764    
1765        // --
1766        // Code generation methods.
1767        // --
1768        private void generateProperty( final String name, final Class<?> type, final ClassOutline c )
1769        {
1770            final char[] chars = name.toCharArray();
1771            chars[0] = Character.toUpperCase( chars[0] );
1772            final String publicName = String.valueOf( chars );
1773            final String getterName = ( type == Boolean.TYPE || type == Boolean.class ? "is" : "get" ) + publicName;
1774            final JFieldVar field = c.implClass.field( JMod.PROTECTED, type, name );
1775            field.annotate( XmlTransient.class );
1776    
1777            final JMethod getter = c.implClass.method( JMod.PUBLIC, type, getterName );
1778            getter.body().directStatement( "// " + getMessage( "title" ) );
1779            getter.body()._return( field );
1780    
1781            final JMethod setter = c.implClass.method( JMod.PUBLIC, c.parent().getCodeModel().VOID,
1782                                                       "set" + String.valueOf( chars ) );
1783    
1784            final JVar valueParam = setter.param( JMod.FINAL, type, "value" );
1785            setter.body().directStatement( "// " + getMessage( "title" ) );
1786            setter.body().assign( JExpr._this().ref( field ), valueParam );
1787    
1788            getter.javadoc().append( "Gets the value of the " + name + " property." );
1789            getter.javadoc().addReturn().append( "The value of the " + name + " property." );
1790    
1791            setter.javadoc().append( "Sets the value of the " + name + " property." );
1792            setter.javadoc().addParam( valueParam ).append( "The new value of the " + name + " property." );
1793        }
1794    
1795        private void generateCollectionSetter( final JCodeModel cm, final ClassOutline c, final CPropertyInfo p )
1796        {
1797            final JFieldVar field = c.implClass.fields().get( p.getName( false ) );
1798            final JMethod setter = c.implClass.method( JMod.PUBLIC, cm.VOID, "set" + p.getName( true ) );
1799            final JVar valueParam = setter.param( JMod.FINAL, field.type(), "value" );
1800            final JBlock body = setter.body();
1801            body.directStatement( "// " + getMessage( "title" ) );
1802            body.assign( JExpr._this().ref( field ), valueParam );
1803    
1804            setter.javadoc().append( "Sets the value of the " + p.getName( false ) + " property." );
1805            setter.javadoc().addParam( valueParam ).append( "The new value of the " + p.getName( false ) + " property." );
1806        }
1807    
1808        private void generateTemporalBasic( final FieldOutline f )
1809        {
1810            // Getter.
1811            final String lineSeparator = System.getProperty( "line.separator" );
1812            final JFieldVar field = f.parent().implClass.field( JMod.PROTECTED, f.parent().parent().getCodeModel().ref(
1813                "java.util.Calendar" ), "jpa" + f.getPropertyInfo().getName( true ) );
1814    
1815            field.annotate( XmlTransient.class );
1816    
1817            final JMethod getter =
1818                f.parent().implClass.method( JMod.PUBLIC, f.parent().parent().getCodeModel().ref( Calendar.class ),
1819                                             "getJpa" + f.getPropertyInfo().getName( true ) );
1820    
1821            getter.body().directStatement( "// " + getMessage( "title" ) );
1822            getter.body().assign( JExpr.refthis( field.name() ), f.parent()._package().objectFactory().
1823                staticInvoke( "createCalendar" ).arg( JExpr.refthis( f.getPropertyInfo().getName( false ) ) ) );
1824    
1825            getter.body()._return( JExpr.refthis( field.name() ) );
1826    
1827            getter.javadoc().append(
1828                "Gets the value of the jpa" + f.getPropertyInfo().getName( true ) + " property." + lineSeparator );
1829    
1830            getter.javadoc().append(
1831                "<p>This method returns the value of the " + f.getPropertyInfo().getName( false ) + " property "
1832                + "transformed to a " + Calendar.class.getName() + " instance.</p>" + lineSeparator );
1833    
1834            getter.javadoc().addReturn().append(
1835                "The value of the jpa" + f.getPropertyInfo().getName( true ) + " property." );
1836    
1837            // Setter.
1838            final JMethod setter = f.parent().implClass.method(
1839                JMod.PUBLIC, f.parent().parent().getCodeModel().VOID, "setJpa" + f.getPropertyInfo().getName( true ) );
1840    
1841            final JVar calendar = setter.param( JMod.FINAL, Calendar.class, "value" );
1842    
1843            setter.body().directStatement( "// " + getMessage( "title" ) );
1844            setter.body().assign( JExpr.refthis( field.name() ), calendar );
1845            setter.body().assign( JExpr.refthis( f.getPropertyInfo().getName( false ) ), f.parent()._package().
1846                objectFactory().staticInvoke( "createXMLGregorianCalendar" ).arg( calendar ) );
1847    
1848            // Update to the JAXB property setter to also update the jpa field.
1849            final JMethod transientSetter = this.getSetter( f );
1850            transientSetter.body().assign( JExpr.refthis( field.name() ), f.parent()._package().objectFactory().
1851                staticInvoke( "createCalendar" ).arg( transientSetter.listParams()[0] ) );
1852    
1853            setter.javadoc().append(
1854                "Sets the value of the jpa" + f.getPropertyInfo().getName( true ) + " property." + lineSeparator );
1855    
1856            setter.javadoc().append(
1857                "<p>This method sets the value of the " + f.getPropertyInfo().getName( false ) + " property by "
1858                + "transforming {@code " + calendar.name() + "} to a " + XMLGregorianCalendar.class.getName()
1859                + " instance.</p>" + lineSeparator );
1860    
1861            setter.javadoc().addParam( calendar ).append(
1862                "The new value of the jpa" + f.getPropertyInfo().getName( true ) + " property." );
1863    
1864        }
1865    
1866        private void generateAdapterMethods( final JCodeModel cm, final PackageOutline p )
1867        {
1868            final JDefinedClass of = p.objectFactory();
1869    
1870            // createCalendar
1871            final JMethod createCalendar = of.method( JMod.STATIC, cm.ref( Calendar.class ), "createCalendar" );
1872            JVar value = createCalendar.param( JMod.FINAL, XMLGregorianCalendar.class, "value" );
1873            createCalendar.body().directStatement( "// " + getMessage( "title" ) );
1874            createCalendar.body()._return(
1875                JOp.cond( value.eq( JExpr._null() ), JExpr._null(), value.invoke( "toGregorianCalendar" ) ) );
1876    
1877            createCalendar.javadoc().append( "Creates a " + Calendar.class.getName() + " instance from a "
1878                                             + XMLGregorianCalendar.class.getName() + " instance." );
1879    
1880            createCalendar.javadoc().addParam( value ).append(
1881                "The " + XMLGregorianCalendar.class.getName() + " instance or {@code null}." );
1882    
1883            createCalendar.javadoc().addReturn().append(
1884                "A " + Calendar.class.getName() + " instance created from {@code " + value.name()
1885                + "} or {@code null} if {@code " + value.name() + "} is {@code null}." );
1886    
1887            // createXMLGregorianCalendar
1888            final JMethod createXMLGregorianCalendar =
1889                of.method( JMod.STATIC, XMLGregorianCalendar.class, "createXMLGregorianCalendar" );
1890    
1891            createXMLGregorianCalendar.body().directStatement( "// " + getMessage( "title" ) );
1892            value = createXMLGregorianCalendar.param( JMod.FINAL, Calendar.class, "value" );
1893    
1894            final JTryBlock tryBlock = createXMLGregorianCalendar.body()._try();
1895            final JConditional notNull = tryBlock.body()._if( value.ne( JExpr._null() ) );
1896    
1897            final JVar calendar = notNull._then().decl( cm.ref( GregorianCalendar.class ), "calendar" );
1898            calendar.init( JExpr._new( cm.ref( GregorianCalendar.class ) ) );
1899            notNull._then().add( calendar.invoke( "setTimeZone" ).arg( value.invoke( "getTimeZone" ) ) );
1900            notNull._then().add( calendar.invoke( "setTimeInMillis" ).arg( value.invoke( "getTimeInMillis" ) ) );
1901            notNull._then()._return( cm.ref( DatatypeFactory.class ).staticInvoke( "newInstance" ).invoke(
1902                "newXMLGregorianCalendar" ).arg( calendar ) );
1903    
1904            tryBlock.body()._return( JExpr._null() );
1905    
1906            final JCatchBlock catchBlock = tryBlock._catch( cm.ref( DatatypeConfigurationException.class ) );
1907            catchBlock.body()._throw( JExpr._new( cm.ref( AssertionError.class ) ).arg( catchBlock.param( "e" ) ) );
1908    
1909            createXMLGregorianCalendar.javadoc().append(
1910                "Creates a " + XMLGregorianCalendar.class.getName() + " instance from a " + Calendar.class.getName()
1911                + " instance." );
1912    
1913            createXMLGregorianCalendar.javadoc().addParam( value ).append(
1914                "The " + Calendar.class.getName() + " instance or {@code null}." );
1915    
1916            createXMLGregorianCalendar.javadoc().addReturn().append(
1917                "A " + XMLGregorianCalendar.class.getName() + " instance created from {@code " + value.name()
1918                + "} or {@code null} if {@code " + value.name() + "} is {@code null}." );
1919    
1920        }
1921    
1922        // --
1923        // Methods for annotating classes.
1924        // --
1925        private void annotate( final Outline outline, final EntityMappings orm )
1926        {
1927            for ( Iterator<Entity> it = orm.getEntity().iterator(); it.hasNext(); )
1928            {
1929                this.annotateEntity( outline, it.next() );
1930            }
1931            for ( Iterator<Embeddable> it = orm.getEmbeddable().iterator(); it.hasNext(); )
1932            {
1933                this.annotateEmbeddable( outline, it.next() );
1934            }
1935            for ( Iterator<MappedSuperclass> it = orm.getMappedSuperclass().iterator(); it.hasNext(); )
1936            {
1937                this.annotateMappedSuperclass( outline, it.next() );
1938            }
1939        }
1940    
1941        private void annotateMappedSuperclass( final Outline outline, final MappedSuperclass ms )
1942        {
1943            final JCodeModel cm = outline.getCodeModel();
1944            final ClassOutline c = this.getClassOutline( outline, ms.getClazz() );
1945            c.implClass.annotate( cm.ref( javax.persistence.MappedSuperclass.class ) );
1946    
1947            if ( ms.getAttributes() != null )
1948            {
1949                this.annotate( cm, c, ms.getAttributes() );
1950            }
1951            if ( ms.getEntityListeners() != null )
1952            {
1953                this.annotate( c, ms.getEntityListeners() );
1954            }
1955            if ( ms.getExcludeDefaultListeners() != null )
1956            {
1957                c.implClass.annotate( c.parent().getCodeModel().ref( javax.persistence.ExcludeDefaultListeners.class ) );
1958            }
1959            if ( ms.getExcludeSuperclassListeners() != null )
1960            {
1961                c.implClass.annotate( c.parent().getCodeModel().ref( javax.persistence.ExcludeSuperclassListeners.class ) );
1962            }
1963            if ( ms.getIdClass() != null )
1964            {
1965                this.annotate( c, ms.getIdClass() );
1966            }
1967            if ( ms.getPostLoad() != null )
1968            {
1969                final JMethod m = this.getMethod( c, ms.getPostLoad().getMethodName() );
1970                m.annotate( cm.ref( javax.persistence.PostLoad.class ) );
1971            }
1972            if ( ms.getPostPersist() != null )
1973            {
1974                final JMethod m = this.getMethod( c, ms.getPostPersist().getMethodName() );
1975                m.annotate( cm.ref( javax.persistence.PostPersist.class ) );
1976            }
1977            if ( ms.getPostRemove() != null )
1978            {
1979                final JMethod m = this.getMethod( c, ms.getPostRemove().getMethodName() );
1980                m.annotate( cm.ref( javax.persistence.PostRemove.class ) );
1981            }
1982            if ( ms.getPostUpdate() != null )
1983            {
1984                final JMethod m = this.getMethod( c, ms.getPostUpdate().getMethodName() );
1985                m.annotate( cm.ref( javax.persistence.PostUpdate.class ) );
1986            }
1987            if ( ms.getPrePersist() != null )
1988            {
1989                final JMethod m = this.getMethod( c, ms.getPreUpdate().getMethodName() );
1990                m.annotate( cm.ref( javax.persistence.PrePersist.class ) );
1991            }
1992            if ( ms.getPreRemove() != null )
1993            {
1994                final JMethod m = this.getMethod( c, ms.getPreRemove().getMethodName() );
1995                m.annotate( cm.ref( javax.persistence.PreRemove.class ) );
1996            }
1997            if ( ms.getPreUpdate() != null )
1998            {
1999                final JMethod m = this.getMethod( c, ms.getPreUpdate().getMethodName() );
2000                m.annotate( cm.ref( javax.persistence.PreUpdate.class ) );
2001            }
2002        }
2003    
2004        private void annotateEmbeddable( final Outline outline, final Embeddable embeddable )
2005        {
2006            final JCodeModel cm = outline.getCodeModel();
2007            final ClassOutline c = this.getClassOutline( outline, embeddable.getClazz() );
2008            c.implClass.annotate( cm.ref( javax.persistence.Embeddable.class ) );
2009    
2010            if ( embeddable.getAttributes() != null )
2011            {
2012                this.annotate( c, embeddable.getAttributes() );
2013            }
2014        }
2015    
2016        private void annotateEntity( final Outline outline, final Entity entity )
2017        {
2018            final JCodeModel cm = outline.getCodeModel();
2019            final ClassOutline c = this.getClassOutline( outline, entity.getClazz() );
2020            final JAnnotationUse a = c.implClass.annotate( cm.ref( javax.persistence.Entity.class ) );
2021    
2022            if ( entity.getName() != null )
2023            {
2024                a.param( "name", entity.getName() );
2025            }
2026    
2027            if ( !entity.getAssociationOverride().isEmpty() )
2028            {
2029                final JAnnotationUse aolst = c.implClass.annotate( cm.ref( javax.persistence.AssociationOverrides.class ) );
2030                final JAnnotationArrayMember value = aolst.paramArray( "value" );
2031                for ( AssociationOverride o : entity.getAssociationOverride() )
2032                {
2033                    final JAnnotationUse ao = value.annotate( cm.ref( javax.persistence.AssociationOverride.class ) );
2034                    if ( o.getName() != null )
2035                    {
2036                        ao.param( "name", o.getName() );
2037                    }
2038    
2039                    if ( !o.getJoinColumn().isEmpty() )
2040                    {
2041                        final JAnnotationArrayMember joinColumns = ao.paramArray( "joinColumns" );
2042                        for ( JoinColumn jc : o.getJoinColumn() )
2043                        {
2044                            final JAnnotationUse jca = joinColumns.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2045                            this.annotate( jca, jc );
2046                        }
2047                    }
2048                }
2049            }
2050    
2051            if ( !entity.getAttributeOverride().isEmpty() )
2052            {
2053                final JAnnotationUse aolst = c.implClass.annotate( cm.ref( javax.persistence.AttributeOverrides.class ) );
2054                final JAnnotationArrayMember value = aolst.paramArray( "value" );
2055                for ( AttributeOverride o : entity.getAttributeOverride() )
2056                {
2057                    final JAnnotationUse ao = value.annotate( cm.ref( javax.persistence.AttributeOverride.class ) );
2058                    if ( o.getColumn() != null )
2059                    {
2060                        final JAnnotationUse ac = ao.param( "column", cm.ref( javax.persistence.Column.class ) );
2061                        this.annotate( ac, o.getColumn() );
2062                    }
2063                    if ( o.getName() != null )
2064                    {
2065                        ao.param( "name", o.getName() );
2066                    }
2067                }
2068            }
2069    
2070            if ( entity.getAttributes() != null )
2071            {
2072                this.annotate( cm, c, entity.getAttributes() );
2073            }
2074    
2075            if ( entity.getDiscriminatorColumn() != null )
2076            {
2077                final JAnnotationUse dc = c.implClass.annotate( cm.ref( javax.persistence.DiscriminatorColumn.class ) );
2078                if ( entity.getDiscriminatorColumn().getColumnDefinition() != null )
2079                {
2080                    dc.param( "columnDefinition", entity.getDiscriminatorColumn().getColumnDefinition() );
2081                }
2082                if ( entity.getDiscriminatorColumn().getDiscriminatorType() != null )
2083                {
2084                    dc.param( "discriminatorType", javax.persistence.DiscriminatorType.valueOf(
2085                        entity.getDiscriminatorColumn().getDiscriminatorType().value() ) );
2086    
2087                }
2088                if ( entity.getDiscriminatorColumn().getLength() != null )
2089                {
2090                    dc.param( "length", entity.getDiscriminatorColumn().getLength().intValue() );
2091                }
2092                if ( entity.getDiscriminatorColumn().getName() != null )
2093                {
2094                    dc.param( "name", entity.getDiscriminatorColumn().getName() );
2095                }
2096            }
2097    
2098            if ( entity.getDiscriminatorValue() != null )
2099            {
2100                final JAnnotationUse dv = c.implClass.annotate( cm.ref( javax.persistence.DiscriminatorValue.class ) );
2101                dv.param( "value", entity.getDiscriminatorValue() );
2102            }
2103    
2104            if ( entity.getEntityListeners() != null )
2105            {
2106                this.annotate( c, entity.getEntityListeners() );
2107            }
2108    
2109            if ( entity.getExcludeDefaultListeners() != null )
2110            {
2111                c.implClass.annotate( cm.ref( javax.persistence.ExcludeDefaultListeners.class ) );
2112            }
2113            if ( entity.getExcludeSuperclassListeners() != null )
2114            {
2115                c.implClass.annotate( cm.ref( javax.persistence.ExcludeSuperclassListeners.class ) );
2116            }
2117            if ( entity.getIdClass() != null )
2118            {
2119                this.annotate( c, entity.getIdClass() );
2120            }
2121            if ( entity.getInheritance() != null )
2122            {
2123                final JAnnotationUse ih = c.implClass.annotate( cm.ref( javax.persistence.Inheritance.class ) );
2124                ih.param( "strategy",
2125                          javax.persistence.InheritanceType.valueOf( entity.getInheritance().getStrategy().value() ) );
2126    
2127            }
2128            if ( !entity.getNamedNativeQuery().isEmpty() )
2129            {
2130                final JAnnotationUse nnqlst = c.implClass.annotate( cm.ref( javax.persistence.NamedNativeQueries.class ) );
2131                final JAnnotationArrayMember value = nnqlst.paramArray( "value" );
2132                for ( NamedNativeQuery q : entity.getNamedNativeQuery() )
2133                {
2134                    final JAnnotationUse qa = value.annotate( cm.ref( javax.persistence.NamedNativeQuery.class ) );
2135                    qa.param( "name", q.getName() );
2136                    qa.param( "query", q.getQuery() );
2137    
2138                    if ( q.getResultClass() != null )
2139                    {
2140                        qa.param( "resultClass", cm.ref( q.getResultClass() ) );
2141                    }
2142                    if ( q.getResultSetMapping() != null )
2143                    {
2144                        qa.param( "resultSetMapping", q.getResultSetMapping() );
2145                    }
2146                    if ( !q.getHint().isEmpty() )
2147                    {
2148                        final JAnnotationArrayMember hints = qa.paramArray( "hints" );
2149                        for ( QueryHint hint : q.getHint() )
2150                        {
2151                            final JAnnotationUse qh = hints.annotate( javax.persistence.QueryHint.class );
2152                            qh.param( "name", hint.getName() );
2153                            qh.param( "value", hint.getValue() );
2154                        }
2155                    }
2156                }
2157            }
2158            if ( !entity.getNamedQuery().isEmpty() )
2159            {
2160                final JAnnotationUse nqlst = c.implClass.annotate( cm.ref( javax.persistence.NamedQueries.class ) );
2161                final JAnnotationArrayMember value = nqlst.paramArray( "value" );
2162                for ( NamedQuery q : entity.getNamedQuery() )
2163                {
2164                    final JAnnotationUse nq = value.annotate( cm.ref( javax.persistence.NamedQuery.class ) );
2165                    nq.param( "name", q.getName() );
2166                    nq.param( "query", q.getQuery() );
2167    
2168                    if ( !q.getHint().isEmpty() )
2169                    {
2170                        final JAnnotationArrayMember hints = nq.paramArray( "hints" );
2171                        for ( QueryHint hint : q.getHint() )
2172                        {
2173                            final JAnnotationUse qh = hints.annotate( javax.persistence.QueryHint.class );
2174                            qh.param( "name", hint.getName() );
2175                            qh.param( "value", hint.getValue() );
2176                        }
2177                    }
2178                }
2179            }
2180            if ( entity.getPostLoad() != null )
2181            {
2182                final JMethod m = this.getMethod( c, entity.getPostLoad().getMethodName() );
2183                m.annotate( cm.ref( javax.persistence.PostLoad.class ) );
2184            }
2185            if ( entity.getPostPersist() != null )
2186            {
2187                final JMethod m = this.getMethod( c, entity.getPostPersist().getMethodName() );
2188                m.annotate( cm.ref( javax.persistence.PostPersist.class ) );
2189            }
2190            if ( entity.getPostRemove() != null )
2191            {
2192                final JMethod m = this.getMethod( c, entity.getPostRemove().getMethodName() );
2193                m.annotate( cm.ref( javax.persistence.PostRemove.class ) );
2194            }
2195            if ( entity.getPostUpdate() != null )
2196            {
2197                final JMethod m = this.getMethod( c, entity.getPostUpdate().getMethodName() );
2198                m.annotate( cm.ref( javax.persistence.PostUpdate.class ) );
2199            }
2200            if ( entity.getPrePersist() != null )
2201            {
2202                final JMethod m = this.getMethod( c, entity.getPreUpdate().getMethodName() );
2203                m.annotate( cm.ref( javax.persistence.PrePersist.class ) );
2204            }
2205            if ( entity.getPreRemove() != null )
2206            {
2207                final JMethod m = this.getMethod( c, entity.getPreRemove().getMethodName() );
2208                m.annotate( cm.ref( javax.persistence.PreRemove.class ) );
2209            }
2210            if ( entity.getPreUpdate() != null )
2211            {
2212                final JMethod m = this.getMethod( c, entity.getPreUpdate().getMethodName() );
2213                m.annotate( cm.ref( javax.persistence.PreUpdate.class ) );
2214            }
2215            if ( !entity.getPrimaryKeyJoinColumn().isEmpty() )
2216            {
2217                final JAnnotationUse pkjcs = c.implClass.annotate( cm.ref( javax.persistence.PrimaryKeyJoinColumns.class ) );
2218                final JAnnotationArrayMember pkjc = pkjcs.paramArray( "value" );
2219                this.annotate( cm, pkjc, entity.getPrimaryKeyJoinColumn() );
2220            }
2221            if ( !entity.getSecondaryTable().isEmpty() )
2222            {
2223                final JAnnotationUse stlst = c.implClass.annotate( cm.ref( javax.persistence.SecondaryTables.class ) );
2224                final JAnnotationArrayMember value = stlst.paramArray( "value" );
2225                for ( SecondaryTable t : entity.getSecondaryTable() )
2226                {
2227                    final JAnnotationUse st = value.annotate( cm.ref( javax.persistence.SecondaryTable.class ) );
2228                    if ( t.getCatalog() != null )
2229                    {
2230                        st.param( "catalog", t.getCatalog() );
2231                    }
2232                    if ( t.getName() != null )
2233                    {
2234                        st.param( "name", t.getName() );
2235                    }
2236                    if ( !t.getPrimaryKeyJoinColumn().isEmpty() )
2237                    {
2238                        final JAnnotationArrayMember pkjc = st.paramArray( "pkJoinColumns" );
2239                        this.annotate( cm, pkjc, entity.getPrimaryKeyJoinColumn() );
2240                    }
2241                    if ( t.getSchema() != null )
2242                    {
2243                        st.param( "schema", t.getSchema() );
2244                    }
2245                    if ( !t.getUniqueConstraint().isEmpty() )
2246                    {
2247                        final JAnnotationArrayMember uca = st.paramArray( "uniqueConstraints" );
2248                        for ( UniqueConstraint uc : t.getUniqueConstraint() )
2249                        {
2250                            final JAnnotationUse u = uca.annotate( javax.persistence.UniqueConstraint.class );
2251                            final JAnnotationArrayMember colNames = u.paramArray( "columnNames" );
2252                            for ( String cn : uc.getColumnName() )
2253                            {
2254                                colNames.param( cn );
2255                            }
2256                        }
2257                    }
2258                }
2259            }
2260            if ( entity.getSequenceGenerator() != null )
2261            {
2262                final JAnnotationUse sg = c.implClass.annotate( cm.ref( javax.persistence.SequenceGenerator.class ) );
2263                this.annotate( sg, entity.getSequenceGenerator() );
2264            }
2265            if ( !entity.getSqlResultSetMapping().isEmpty() )
2266            {
2267                final JAnnotationUse lst = c.implClass.annotate( cm.ref( javax.persistence.SqlResultSetMappings.class ) );
2268                final JAnnotationArrayMember value = lst.paramArray( "value" );
2269                for ( SqlResultSetMapping m : entity.getSqlResultSetMapping() )
2270                {
2271                    final JAnnotationUse srsm = value.annotate( cm.ref( javax.persistence.SqlResultSetMapping.class ) );
2272                    if ( !m.getColumnResult().isEmpty() )
2273                    {
2274                        final JAnnotationArrayMember cols = srsm.paramArray( "columns" );
2275                        for ( ColumnResult cr : m.getColumnResult() )
2276                        {
2277                            final JAnnotationUse cra = cols.annotate( javax.persistence.ColumnResult.class );
2278                            cra.param( "name", cr.getName() );
2279                        }
2280                    }
2281                    if ( !m.getEntityResult().isEmpty() )
2282                    {
2283                        final JAnnotationArrayMember entities = srsm.paramArray( "entities" );
2284                        for ( EntityResult er : m.getEntityResult() )
2285                        {
2286                            final JAnnotationUse era = entities.annotate( javax.persistence.EntityResult.class );
2287                            if ( er.getDiscriminatorColumn() != null )
2288                            {
2289                                era.param( "discriminatorColumn", er.getDiscriminatorColumn() );
2290                            }
2291                            if ( er.getEntityClass() != null )
2292                            {
2293                                era.param( "entityClass", cm.ref( er.getEntityClass() ) );
2294                            }
2295                            if ( !er.getFieldResult().isEmpty() )
2296                            {
2297                                final JAnnotationArrayMember fields = era.paramArray( "fields" );
2298                                for ( FieldResult fr : er.getFieldResult() )
2299                                {
2300                                    final JAnnotationUse fra = fields.annotate( javax.persistence.FieldResult.class );
2301                                    if ( fr.getColumn() != null )
2302                                    {
2303                                        fra.param( "column", fr.getColumn() );
2304                                    }
2305                                    if ( fr.getName() != null )
2306                                    {
2307                                        fra.param( "name", fr.getName() );
2308                                    }
2309                                }
2310                            }
2311                        }
2312                    }
2313                    if ( m.getName() != null )
2314                    {
2315                        srsm.param( "name", m.getName() );
2316                    }
2317                }
2318            }
2319            if ( entity.getTable() != null )
2320            {
2321                final JAnnotationUse ta = c.implClass.annotate( cm.ref( javax.persistence.Table.class ) );
2322                if ( entity.getTable().getCatalog() != null )
2323                {
2324                    ta.param( "catalog", entity.getTable().getCatalog() );
2325                }
2326                if ( entity.getTable().getName() != null )
2327                {
2328                    ta.param( "name", entity.getTable().getName() );
2329                }
2330                if ( entity.getTable().getSchema() != null )
2331                {
2332                    ta.param( "schema", entity.getTable().getSchema() );
2333                }
2334                if ( !entity.getTable().getUniqueConstraint().isEmpty() )
2335                {
2336                    final JAnnotationArrayMember uclst = ta.paramArray( "uniqueConstraints" );
2337                    for ( UniqueConstraint uc : entity.getTable().getUniqueConstraint() )
2338                    {
2339                        final JAnnotationUse uca = uclst.annotate( javax.persistence.UniqueConstraint.class );
2340                        final JAnnotationArrayMember colNames = uca.paramArray( "columnNames" );
2341                        for ( String cn : uc.getColumnName() )
2342                        {
2343                            colNames.param( cn );
2344                        }
2345                    }
2346                }
2347            }
2348            if ( entity.getTableGenerator() != null )
2349            {
2350                final JAnnotationUse tg = c.implClass.annotate( cm.ref( javax.persistence.TableGenerator.class ) );
2351                this.annotate( tg, entity.getTableGenerator() );
2352            }
2353        }
2354    
2355        private void annotate( final ClassOutline c, final IdClass id )
2356        {
2357            final JAnnotationUse a =
2358                c.implClass.annotate( c.parent().getCodeModel().ref( javax.persistence.IdClass.class ) );
2359    
2360            a.param( "value", c.parent().getCodeModel().ref( id.getClazz() ) );
2361        }
2362    
2363        private void annotate( final ClassOutline c, final EntityListeners l )
2364        {
2365            final JAnnotationUse lst =
2366                c.implClass.annotate( c.parent().getCodeModel().ref( javax.persistence.EntityListeners.class ) );
2367    
2368            final JAnnotationArrayMember value = lst.paramArray( "value" );
2369            for ( EntityListener el : l.getEntityListener() )
2370            {
2371                value.param( c.parent().getCodeModel().ref( el.getClazz() ) );
2372            }
2373        }
2374    
2375        private void annotate( final JAnnotationUse a, final Column column )
2376        {
2377            if ( column.isInsertable() != null )
2378            {
2379                a.param( "insertable", column.isInsertable().booleanValue() );
2380            }
2381            if ( column.isNullable() != null )
2382            {
2383                a.param( "nullable", column.isNullable().booleanValue() );
2384            }
2385            if ( column.isUnique() != null )
2386            {
2387                a.param( "unique", column.isUnique().booleanValue() );
2388            }
2389            if ( column.isUpdatable() != null )
2390            {
2391                a.param( "updatable", column.isUpdatable().booleanValue() );
2392            }
2393            if ( column.getColumnDefinition() != null )
2394            {
2395                a.param( "columnDefinition", column.getColumnDefinition() );
2396            }
2397            if ( column.getLength() != null )
2398            {
2399                a.param( "length", column.getLength().intValue() );
2400            }
2401            if ( column.getName() != null )
2402            {
2403                a.param( "name", column.getName() );
2404            }
2405            if ( column.getPrecision() != null )
2406            {
2407                a.param( "precision", column.getPrecision().intValue() );
2408            }
2409            if ( column.getScale() != null )
2410            {
2411                a.param( "scale", column.getScale().intValue() );
2412            }
2413            if ( column.getTable() != null )
2414            {
2415                a.param( "table", column.getTable() );
2416            }
2417        }
2418    
2419        private void annotate( final JAnnotationUse a, final JoinColumn column )
2420        {
2421            if ( column.isInsertable() != null )
2422            {
2423                a.param( "insertable", column.isInsertable().booleanValue() );
2424            }
2425            if ( column.isNullable() != null )
2426            {
2427                a.param( "nullable", column.isNullable().booleanValue() );
2428            }
2429            if ( column.isUnique() != null )
2430            {
2431                a.param( "unique", column.isUnique().booleanValue() );
2432            }
2433            if ( column.isUpdatable() != null )
2434            {
2435                a.param( "updatable", column.isUpdatable().booleanValue() );
2436            }
2437            if ( column.getColumnDefinition() != null )
2438            {
2439                a.param( "columnDefinition", column.getColumnDefinition() );
2440            }
2441            if ( column.getName() != null )
2442            {
2443                a.param( "name", column.getName() );
2444            }
2445            if ( column.getReferencedColumnName() != null )
2446            {
2447                a.param( "referencedColumnName", column.getReferencedColumnName() );
2448            }
2449            if ( column.getTable() != null )
2450            {
2451                a.param( "table", column.getTable() );
2452            }
2453        }
2454    
2455        private void annotate( final JCodeModel cm, final JAnnotationUse a, final JoinTable jt )
2456        {
2457            if ( jt.getCatalog() != null )
2458            {
2459                a.param( "catalog", jt.getCatalog() );
2460            }
2461            if ( jt.getName() != null )
2462            {
2463                a.param( "name", jt.getName() );
2464            }
2465            if ( jt.getSchema() != null )
2466            {
2467                a.param( "schema", jt.getSchema() );
2468            }
2469            if ( !jt.getInverseJoinColumn().isEmpty() )
2470            {
2471                final JAnnotationArrayMember ijclst = a.paramArray( "inverseJoinColumns" );
2472                for ( JoinColumn jc : jt.getInverseJoinColumn() )
2473                {
2474                    final JAnnotationUse ijc = ijclst.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2475                    this.annotate( ijc, jc );
2476                }
2477            }
2478            if ( !jt.getJoinColumn().isEmpty() )
2479            {
2480                final JAnnotationArrayMember jclst = a.paramArray( "joinColumns" );
2481                for ( JoinColumn jc : jt.getJoinColumn() )
2482                {
2483                    final JAnnotationUse jca = jclst.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2484                    this.annotate( jca, jc );
2485                }
2486            }
2487            if ( !jt.getUniqueConstraint().isEmpty() )
2488            {
2489                final JAnnotationArrayMember uclst = a.paramArray( "uniqueConstraints" );
2490                for ( UniqueConstraint uc : jt.getUniqueConstraint() )
2491                {
2492                    final JAnnotationUse uca = uclst.annotate( javax.persistence.UniqueConstraint.class );
2493                    final JAnnotationArrayMember colNames = uca.paramArray( "columnNames" );
2494                    for ( String cn : uc.getColumnName() )
2495                    {
2496                        colNames.param( cn );
2497                    }
2498                }
2499            }
2500        }
2501    
2502        private void annotate( final JCodeModel cm, final JAnnotationArrayMember a, final List<PrimaryKeyJoinColumn> cols )
2503        {
2504            for ( PrimaryKeyJoinColumn jc : cols )
2505            {
2506                final JAnnotationUse jca = a.annotate( cm.ref( javax.persistence.PrimaryKeyJoinColumn.class ) );
2507                if ( jc.getColumnDefinition() != null )
2508                {
2509                    jca.param( "columnDefinition", jc.getColumnDefinition() );
2510                }
2511                if ( jc.getName() != null )
2512                {
2513                    jca.param( "name", jc.getName() );
2514                }
2515                if ( jc.getReferencedColumnName() != null )
2516                {
2517                    jca.param( "referenceColumnName", jc.getReferencedColumnName() );
2518                }
2519            }
2520        }
2521    
2522        private void annotate( final JAnnotationUse a, final SequenceGenerator gen )
2523        {
2524            if ( gen.getAllocationSize() != null )
2525            {
2526                a.param( "allocationSize", gen.getAllocationSize().intValue() );
2527            }
2528            if ( gen.getInitialValue() != null )
2529            {
2530                a.param( "initialValue", gen.getInitialValue().intValue() );
2531            }
2532            if ( gen.getName() != null )
2533            {
2534                a.param( "name", gen.getName() );
2535            }
2536            if ( gen.getSequenceName() != null )
2537            {
2538                a.param( "sequenceName", gen.getSequenceName() );
2539            }
2540        }
2541    
2542        private void annotate( final JAnnotationUse a, final TableGenerator gen )
2543        {
2544            if ( gen.getAllocationSize() != null )
2545            {
2546                a.param( "allocationSize", gen.getAllocationSize().intValue() );
2547            }
2548            if ( gen.getCatalog() != null )
2549            {
2550                a.param( "catalog", gen.getCatalog() );
2551            }
2552            if ( gen.getInitialValue() != null )
2553            {
2554                a.param( "initialValue", gen.getInitialValue().intValue() );
2555            }
2556            if ( gen.getName() != null )
2557            {
2558                a.param( "name", gen.getName() );
2559            }
2560            if ( gen.getPkColumnName() != null )
2561            {
2562                a.param( "pkColumnName", gen.getPkColumnName() );
2563            }
2564            if ( gen.getPkColumnValue() != null )
2565            {
2566                a.param( "pkColumnValue", gen.getPkColumnValue() );
2567            }
2568            if ( gen.getSchema() != null )
2569            {
2570                a.param( "schema", gen.getSchema() );
2571            }
2572            if ( gen.getTable() != null )
2573            {
2574                a.param( "table", gen.getTable() );
2575            }
2576            if ( gen.getValueColumnName() != null )
2577            {
2578                a.param( "valueColumnName", gen.getValueColumnName() );
2579            }
2580            if ( !gen.getUniqueConstraint().isEmpty() )
2581            {
2582                final JAnnotationArrayMember uclst = a.paramArray( "uniqueConstraints" );
2583                for ( UniqueConstraint uc : gen.getUniqueConstraint() )
2584                {
2585                    final JAnnotationUse uca = uclst.annotate( javax.persistence.UniqueConstraint.class );
2586                    final JAnnotationArrayMember colNames = uca.paramArray( "columnNames" );
2587                    for ( String cn : uc.getColumnName() )
2588                    {
2589                        colNames.param( cn );
2590                    }
2591                }
2592            }
2593        }
2594    
2595        private void annotate( final JAnnotationUse a, final CascadeType c )
2596        {
2597            if ( c.getCascadeAll() != null )
2598            {
2599                a.param( "cascade", javax.persistence.CascadeType.ALL );
2600            }
2601            if ( c.getCascadeMerge() != null )
2602            {
2603                a.param( "cascade", javax.persistence.CascadeType.MERGE );
2604            }
2605            if ( c.getCascadePersist() != null )
2606            {
2607                a.param( "cascade", javax.persistence.CascadeType.PERSIST );
2608            }
2609            if ( c.getCascadeRefresh() != null )
2610            {
2611                a.param( "cascade", javax.persistence.CascadeType.REFRESH );
2612            }
2613            if ( c.getCascadeRemove() != null )
2614            {
2615                a.param( "cascade", javax.persistence.CascadeType.REMOVE );
2616            }
2617        }
2618    
2619        private void annotate( final JCodeModel cm, final ClassOutline c, final Attributes a )
2620        {
2621            for ( Basic b : a.getBasic() )
2622            {
2623                this.annotate( c, b );
2624            }
2625    
2626            for ( Embedded e : a.getEmbedded() )
2627            {
2628                final JMethod getter = this.getGetter( c, e.getName() );
2629                getter.annotate( cm.ref( javax.persistence.Embedded.class ) );
2630                if ( !e.getAttributeOverride().isEmpty() )
2631                {
2632                    final JAnnotationUse aolst = getter.annotate( cm.ref( javax.persistence.AttributeOverrides.class ) );
2633                    final JAnnotationArrayMember value = aolst.paramArray( "value" );
2634                    for ( AttributeOverride o : e.getAttributeOverride() )
2635                    {
2636                        final JAnnotationUse ao = value.annotate( cm.ref( javax.persistence.AttributeOverride.class ) );
2637                        if ( o.getColumn() != null )
2638                        {
2639                            final JAnnotationUse ac = ao.param( "column", cm.ref( javax.persistence.Column.class ) );
2640                            this.annotate( ac, o.getColumn() );
2641                        }
2642                        if ( o.getName() != null )
2643                        {
2644                            ao.param( "name", o.getName() );
2645                        }
2646                    }
2647                }
2648            }
2649    
2650            if ( a.getEmbeddedId() != null )
2651            {
2652                final JMethod getter = this.getGetter( c, a.getEmbeddedId().getName() );
2653                getter.annotate( cm.ref( javax.persistence.EmbeddedId.class ) );
2654                if ( !a.getEmbeddedId().getAttributeOverride().isEmpty() )
2655                {
2656                    final JAnnotationUse aolst = getter.annotate( cm.ref( javax.persistence.AttributeOverrides.class ) );
2657                    final JAnnotationArrayMember value = aolst.paramArray( "value" );
2658                    for ( AttributeOverride o : a.getEmbeddedId().getAttributeOverride() )
2659                    {
2660                        final JAnnotationUse ao = value.annotate( cm.ref( javax.persistence.AttributeOverride.class ) );
2661                        if ( o.getColumn() != null )
2662                        {
2663                            final JAnnotationUse ac = ao.param( "column", cm.ref( javax.persistence.Column.class ) );
2664                            this.annotate( ac, o.getColumn() );
2665                        }
2666                        if ( o.getName() != null )
2667                        {
2668                            ao.param( "name", o.getName() );
2669                        }
2670                    }
2671                }
2672            }
2673    
2674            for ( Id i : a.getId() )
2675            {
2676                final JMethod getter = this.getGetter( c, i.getName() );
2677                getter.annotate( cm.ref( javax.persistence.Id.class ) );
2678                if ( i.getColumn() != null )
2679                {
2680                    final JAnnotationUse column = getter.annotate( cm.ref( javax.persistence.Column.class ) );
2681                    this.annotate( column, i.getColumn() );
2682                }
2683                if ( i.getGeneratedValue() != null )
2684                {
2685                    final JAnnotationUse gv = getter.annotate( cm.ref( javax.persistence.GeneratedValue.class ) );
2686                    if ( i.getGeneratedValue().getGenerator() != null )
2687                    {
2688                        gv.param( "generator", i.getGeneratedValue().getGenerator() );
2689                    }
2690                    if ( i.getGeneratedValue().getStrategy() != null )
2691                    {
2692                        gv.param( "strategy", javax.persistence.GenerationType.valueOf(
2693                            i.getGeneratedValue().getStrategy().value() ) );
2694    
2695                    }
2696                }
2697                if ( i.getSequenceGenerator() != null )
2698                {
2699                    final JAnnotationUse gen = getter.annotate( cm.ref( javax.persistence.SequenceGenerator.class ) );
2700                    this.annotate( gen, i.getSequenceGenerator() );
2701                }
2702                if ( i.getTableGenerator() != null )
2703                {
2704                    final JAnnotationUse gen = getter.annotate( cm.ref( javax.persistence.TableGenerator.class ) );
2705                    this.annotate( gen, i.getTableGenerator() );
2706                }
2707                if ( i.getTemporal() != null )
2708                {
2709                    final JAnnotationUse temp = getter.annotate( cm.ref( javax.persistence.Temporal.class ) );
2710                    temp.param( "value", javax.persistence.TemporalType.valueOf( i.getTemporal().value() ) );
2711                }
2712            }
2713    
2714            for ( ManyToMany m : a.getManyToMany() )
2715            {
2716                final JMethod getter = this.getGetter( c, m.getName() );
2717                final JAnnotationUse m2m = getter.annotate( cm.ref( javax.persistence.ManyToMany.class ) );
2718    
2719                if ( m.getCascade() != null )
2720                {
2721                    this.annotate( m2m, m.getCascade() );
2722                }
2723                if ( m.getFetch() != null )
2724                {
2725                    m2m.param( "fetch", javax.persistence.FetchType.valueOf( m.getFetch().value() ) );
2726                }
2727                if ( m.getJoinTable() != null )
2728                {
2729                    final JAnnotationUse jt = getter.annotate( cm.ref( javax.persistence.JoinTable.class ) );
2730                    this.annotate( cm, jt, m.getJoinTable() );
2731                }
2732                if ( m.getMapKey() != null )
2733                {
2734                    final JAnnotationUse mk = getter.annotate( cm.ref( javax.persistence.MapKey.class ) );
2735                    mk.param( "name", m.getMapKey().getName() );
2736                }
2737                if ( m.getMappedBy() != null )
2738                {
2739                    m2m.param( "mappedBy", m.getMappedBy() );
2740                }
2741                if ( m.getOrderBy() != null )
2742                {
2743                    final JAnnotationUse ob = getter.annotate( cm.ref( javax.persistence.OrderBy.class ) );
2744                    ob.param( "value", m.getOrderBy() );
2745                }
2746                if ( m.getTargetEntity() != null )
2747                {
2748                    m2m.param( "targetEntity", cm.ref( m.getTargetEntity() ) );
2749                }
2750            }
2751    
2752            for ( ManyToOne m : a.getManyToOne() )
2753            {
2754                final JMethod getter = this.getGetter( c, m.getName() );
2755                final JAnnotationUse m2o = getter.annotate( cm.ref( javax.persistence.ManyToOne.class ) );
2756                if ( m.getCascade() != null )
2757                {
2758                    this.annotate( m2o, m.getCascade() );
2759                }
2760                if ( m.getFetch() != null )
2761                {
2762                    m2o.param( "fetch", javax.persistence.FetchType.valueOf( m.getFetch().value() ) );
2763                }
2764                if ( !m.getJoinColumn().isEmpty() )
2765                {
2766                    for ( JoinColumn jc : m.getJoinColumn() )
2767                    {
2768                        final JAnnotationUse jca = getter.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2769                        this.annotate( jca, jc );
2770                    }
2771                }
2772                if ( m.getJoinTable() != null )
2773                {
2774                    final JAnnotationUse jt = getter.annotate( cm.ref( javax.persistence.JoinTable.class ) );
2775                    this.annotate( cm, jt, m.getJoinTable() );
2776                }
2777                if ( m.getTargetEntity() != null )
2778                {
2779                    m2o.param( "targetEntity", cm.ref( m.getTargetEntity() ) );
2780                }
2781                if ( m.isOptional() != null )
2782                {
2783                    m2o.param( "optional", m.isOptional().booleanValue() );
2784                }
2785            }
2786    
2787            for ( OneToMany m : a.getOneToMany() )
2788            {
2789                final JMethod getter = this.getGetter( c, m.getName() );
2790                final JAnnotationUse o2m = getter.annotate( cm.ref( javax.persistence.OneToMany.class ) );
2791    
2792                if ( m.getCascade() != null )
2793                {
2794                    this.annotate( o2m, m.getCascade() );
2795                }
2796                if ( m.getFetch() != null )
2797                {
2798                    o2m.param( "fetch", javax.persistence.FetchType.valueOf( m.getFetch().value() ) );
2799                }
2800                if ( !m.getJoinColumn().isEmpty() )
2801                {
2802                    for ( JoinColumn jc : m.getJoinColumn() )
2803                    {
2804                        final JAnnotationUse jca = getter.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2805                        this.annotate( jca, jc );
2806                    }
2807                }
2808                if ( m.getJoinTable() != null )
2809                {
2810                    final JAnnotationUse jt = getter.annotate( cm.ref( javax.persistence.JoinTable.class ) );
2811                    this.annotate( cm, jt, m.getJoinTable() );
2812                }
2813                if ( m.getMapKey() != null )
2814                {
2815                    final JAnnotationUse mk = getter.annotate( cm.ref( javax.persistence.MapKey.class ) );
2816                    mk.param( "name", m.getMapKey().getName() );
2817                }
2818                if ( m.getMappedBy() != null )
2819                {
2820                    o2m.param( "mappedBy", m.getMappedBy() );
2821                }
2822                if ( m.getOrderBy() != null )
2823                {
2824                    final JAnnotationUse ob = getter.annotate( cm.ref( javax.persistence.OrderBy.class ) );
2825                    ob.param( "value", m.getOrderBy() );
2826                }
2827                if ( m.getTargetEntity() != null )
2828                {
2829                    o2m.param( "targetEntity", cm.ref( m.getTargetEntity() ) );
2830                }
2831            }
2832    
2833            for ( OneToOne m : a.getOneToOne() )
2834            {
2835                final JMethod getter = this.getGetter( c, m.getName() );
2836                final JAnnotationUse o2o = getter.annotate( cm.ref( javax.persistence.OneToOne.class ) );
2837                if ( m.getCascade() != null )
2838                {
2839                    this.annotate( o2o, m.getCascade() );
2840                }
2841                if ( m.isOptional() != null )
2842                {
2843                    o2o.param( "optional", m.isOptional().booleanValue() );
2844                }
2845                if ( m.getFetch() != null )
2846                {
2847                    o2o.param( "fetch", javax.persistence.FetchType.valueOf( m.getFetch().value() ) );
2848                }
2849                if ( !m.getJoinColumn().isEmpty() )
2850                {
2851                    for ( JoinColumn jc : m.getJoinColumn() )
2852                    {
2853                        final JAnnotationUse jca = getter.annotate( cm.ref( javax.persistence.JoinColumn.class ) );
2854                        this.annotate( jca, jc );
2855                    }
2856                }
2857                if ( m.getJoinTable() != null )
2858                {
2859                    final JAnnotationUse jt = getter.annotate( cm.ref( javax.persistence.JoinTable.class ) );
2860                    this.annotate( cm, jt, m.getJoinTable() );
2861                }
2862                if ( m.getMappedBy() != null )
2863                {
2864                    o2o.param( "mappedBy", m.getMappedBy() );
2865                }
2866                if ( !m.getPrimaryKeyJoinColumn().isEmpty() )
2867                {
2868                    final JAnnotationUse pkjcs = getter.annotate( cm.ref( javax.persistence.PrimaryKeyJoinColumns.class ) );
2869                    final JAnnotationArrayMember pkjc = pkjcs.paramArray( "value" );
2870                    this.annotate( cm, pkjc, m.getPrimaryKeyJoinColumn() );
2871                }
2872                if ( m.getTargetEntity() != null )
2873                {
2874                    o2o.param( "targetEntity", cm.ref( m.getTargetEntity() ) );
2875                }
2876            }
2877    
2878            for ( Transient t : a.getTransient() )
2879            {
2880                this.annotate( c, t );
2881            }
2882    
2883            for ( Version v : a.getVersion() )
2884            {
2885                final JMethod getter = this.getGetter( c, v.getName() );
2886                getter.annotate( cm.ref( javax.persistence.Version.class ) );
2887                if ( v.getColumn() != null )
2888                {
2889                    final JAnnotationUse col = getter.annotate( cm.ref( javax.persistence.Column.class ) );
2890                    this.annotate( col, v.getColumn() );
2891                }
2892                if ( v.getTemporal() != null )
2893                {
2894                    final JAnnotationUse temp = getter.annotate( cm.ref( javax.persistence.Temporal.class ) );
2895                    temp.param( "value", javax.persistence.TemporalType.valueOf( v.getTemporal().value() ) );
2896                }
2897            }
2898        }
2899    
2900        private void annotate( final ClassOutline c, final EmbeddableAttributes a )
2901        {
2902            if ( !a.getBasic().isEmpty() )
2903            {
2904                for ( Basic b : a.getBasic() )
2905                {
2906                    this.annotate( c, b );
2907                }
2908            }
2909            if ( !a.getTransient().isEmpty() )
2910            {
2911                for ( Transient t : a.getTransient() )
2912                {
2913                    this.annotate( c, t );
2914                }
2915            }
2916        }
2917    
2918        private void annotate( final ClassOutline c, final Transient t )
2919        {
2920            final JMethod getter = this.getGetter( c, t.getName() );
2921            getter.annotate( c.parent().getCodeModel().ref( javax.persistence.Transient.class ) );
2922        }
2923    
2924        private void annotate( final ClassOutline c, final Basic b )
2925        {
2926            final JMethod getter = this.getGetter( c, b.getName() );
2927            final JAnnotationUse ann =
2928                getter.annotate( c.parent().getCodeModel().ref( javax.persistence.Basic.class ) );
2929    
2930            if ( b.isOptional() != null )
2931            {
2932                ann.param( "optional", b.isOptional().booleanValue() );
2933            }
2934            if ( b.getFetch() != null )
2935            {
2936                ann.param( "fetch", javax.persistence.FetchType.valueOf( b.getFetch().value() ) );
2937            }
2938            if ( b.getColumn() != null )
2939            {
2940                final JAnnotationUse ac = getter.annotate(
2941                    c.parent().getCodeModel().ref( javax.persistence.Column.class ) );
2942                this.annotate( ac, b.getColumn() );
2943            }
2944            if ( b.getEnumerated() != null )
2945            {
2946                final JAnnotationUse ac = getter.annotate(
2947                    c.parent().getCodeModel().ref( javax.persistence.Enumerated.class ) );
2948    
2949                ac.param( "value", javax.persistence.EnumType.valueOf( b.getEnumerated().value() ) );
2950            }
2951            if ( b.getLob() != null )
2952            {
2953                getter.annotate( c.parent().getCodeModel().ref( javax.persistence.Lob.class ) );
2954            }
2955            if ( b.getTemporal() != null )
2956            {
2957                final JAnnotationUse ta =
2958                    getter.annotate( c.parent().getCodeModel().ref( javax.persistence.Temporal.class ) );
2959    
2960                ta.param( "value", javax.persistence.TemporalType.valueOf( b.getTemporal().value() ) );
2961            }
2962        }
2963    
2964        // --
2965        // Queries
2966        // --
2967        private Attributes getAttributes( final EntityMappings orm, final String className )
2968        {
2969            for ( Entity e : orm.getEntity() )
2970            {
2971                if ( e.getClazz().equals( className ) )
2972                {
2973                    if ( e.getAttributes() == null )
2974                    {
2975                        e.setAttributes( new Attributes() );
2976                    }
2977    
2978                    return e.getAttributes();
2979                }
2980            }
2981    
2982            for ( MappedSuperclass e : orm.getMappedSuperclass() )
2983            {
2984                if ( e.getClazz().equals( className ) )
2985                {
2986                    if ( e.getAttributes() == null )
2987                    {
2988                        e.setAttributes( new Attributes() );
2989                    }
2990    
2991                    return e.getAttributes();
2992                }
2993            }
2994    
2995            return null;
2996        }
2997    
2998        private ClassOutline getClassOutline( final Outline outline, final String binaryName )
2999        {
3000            for ( ClassOutline c : outline.getClasses() )
3001            {
3002                if ( c.implClass.binaryName().equals( binaryName ) )
3003                {
3004                    return c;
3005                }
3006            }
3007    
3008            return null;
3009        }
3010    
3011        private JMethod getMethod( final ClassOutline c, final String methodName )
3012        {
3013            for ( JMethod m : c.implClass.methods() )
3014            {
3015                if ( m.name().equals( methodName ) )
3016                {
3017                    return m;
3018                }
3019            }
3020    
3021            return null;
3022        }
3023    
3024        private JType[] getBasicTypes()
3025        {
3026            final JCodeModel cm = new JCodeModel();
3027            return new JType[]
3028                {
3029                    cm.BOOLEAN,
3030                    cm.BOOLEAN.boxify(),
3031                    cm.BOOLEAN.array(),
3032                    cm.BOOLEAN.boxify().array(),
3033                    cm.BYTE,
3034                    cm.BYTE.boxify(),
3035                    cm.BYTE.array(),
3036                    cm.BYTE.boxify().array(),
3037                    cm.CHAR,
3038                    cm.CHAR.boxify(),
3039                    cm.CHAR.array(),
3040                    cm.CHAR.boxify().array(),
3041                    cm.DOUBLE,
3042                    cm.DOUBLE.boxify(),
3043                    cm.DOUBLE.array(),
3044                    cm.DOUBLE.boxify().array(),
3045                    cm.FLOAT,
3046                    cm.FLOAT.boxify(),
3047                    cm.FLOAT.array(),
3048                    cm.FLOAT.boxify().array(),
3049                    cm.INT,
3050                    cm.INT.boxify(),
3051                    cm.INT.array(),
3052                    cm.INT.boxify().array(),
3053                    cm.LONG,
3054                    cm.LONG.boxify(),
3055                    cm.LONG.array(),
3056                    cm.LONG.boxify().array(),
3057                    cm.SHORT,
3058                    cm.SHORT.boxify(),
3059                    cm.SHORT.array(),
3060                    cm.SHORT.boxify().array(),
3061                    cm.ref( String.class ),
3062                    cm.ref( BigInteger.class ),
3063                    cm.ref( BigDecimal.class ),
3064                    cm.ref( java.util.Date.class ),
3065                    cm.ref( java.util.Calendar.class ),
3066                    cm.ref( java.sql.Date.class ),
3067                    cm.ref( java.sql.Time.class ),
3068                    cm.ref( java.sql.Timestamp.class )
3069                };
3070        }
3071    
3072        private boolean isBasicFieldOutline( final FieldOutline f )
3073        {
3074            final JType getterType = this.getGetter( f ).type();
3075    
3076            for ( JType t : getBasicTypes() )
3077            {
3078                if ( getterType.binaryName().equals( t.binaryName() ) )
3079                {
3080                    return true;
3081                }
3082            }
3083    
3084            final Collection<? extends CTypeInfo> types = f.getPropertyInfo().ref();
3085            if ( types.size() == 1 )
3086            {
3087                final CTypeInfo type = types.iterator().next();
3088    
3089                return type instanceof CEnumLeafInfo;
3090            }
3091    
3092            return false;
3093        }
3094    
3095        private JMethod getGetter( final ClassOutline c, final String fieldName )
3096        {
3097            JMethod getter = null;
3098            FieldOutline field = null;
3099    
3100            final char[] chars = c.parent().getModel().getNameConverter().toPropertyName( fieldName ).toCharArray();
3101            chars[0] = Character.toUpperCase( chars[0] );
3102            String publicName = String.valueOf( chars );
3103    
3104            for ( FieldOutline f : c.getDeclaredFields() )
3105            {
3106                if ( f.getPropertyInfo().getName( false ).equals( fieldName ) )
3107                {
3108                    field = f;
3109                    break;
3110                }
3111            }
3112    
3113            if ( field != null )
3114            {
3115                publicName = field.getPropertyInfo().getName( true );
3116            }
3117    
3118            getter = c.implClass.getMethod( "get" + publicName, NO_JTYPES );
3119    
3120            if ( getter == null )
3121            {
3122                getter = c.implClass.getMethod( "is" + publicName, NO_JTYPES );
3123            }
3124    
3125            return getter;
3126        }
3127    
3128        private JMethod getGetter( final FieldOutline f )
3129        {
3130            final JDefinedClass clazz = f.parent().implClass;
3131            final String name = f.getPropertyInfo().getName( true );
3132            JMethod getter = clazz.getMethod( "get" + name, NO_JTYPES );
3133    
3134            if ( getter == null )
3135            {
3136                getter = clazz.getMethod( "is" + name, NO_JTYPES );
3137            }
3138    
3139            return getter;
3140        }
3141    
3142        private JMethod getSetter( final FieldOutline f )
3143        {
3144            JMethod setter = null;
3145            final JMethod getter = this.getGetter( f );
3146    
3147            if ( getter != null )
3148            {
3149                final JType t = getter.type();
3150                final JDefinedClass clazz = f.parent().implClass;
3151                final String name = f.getPropertyInfo().getName( true );
3152                setter = clazz.getMethod( "set" + name, new JType[]
3153                    {
3154                        t
3155                    } );
3156    
3157            }
3158    
3159            return setter;
3160        }
3161    
3162        private XSSimpleType getSchemaSimpleType( final XSSimpleType type, final String name )
3163        {
3164            if ( type == null )
3165            {
3166                return null;
3167            }
3168            else if ( type.getOwnerSchema().getTargetNamespace().equals( XMLConstants.W3C_XML_SCHEMA_NS_URI )
3169                      && name.equals( type.getName() ) )
3170            {
3171                return type;
3172            }
3173    
3174            return this.getSchemaSimpleType( type.getSimpleBaseType(), name );
3175        }
3176    
3177        private static String getMessage( final String key, final Object... args )
3178        {
3179            return MessageFormat.format(
3180                ResourceBundle.getBundle( "net/sourceforge/jpaxjc/PluginImpl" ).getString( key ), args );
3181    
3182        }
3183    
3184        private void log( final Level level, final String key, final Object... args )
3185        {
3186            final StringBuffer b = new StringBuffer().append( "[" ).append( MESSAGE_PREFIX ).append( "] [" ).
3187                append( level.getLocalizedName() ).append( "] " ).append( getMessage( key, args ) );
3188    
3189            int logLevel = Level.WARNING.intValue();
3190            if ( this.options != null && !this.options.quiet )
3191            {
3192                if ( this.options.verbose )
3193                {
3194                    logLevel = Level.INFO.intValue();
3195                }
3196                if ( this.options.debugMode )
3197                {
3198                    logLevel = Level.ALL.intValue();
3199                }
3200            }
3201    
3202            if ( level.intValue() >= logLevel )
3203            {
3204                if ( level.intValue() <= Level.INFO.intValue() )
3205                {
3206                    System.out.println( b.toString() );
3207                }
3208                else
3209                {
3210                    System.err.println( b.toString() );
3211                }
3212            }
3213        }
3214    
3215    }