001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.devtools.generators.jpa;
017    
018    import org.kuali.rice.krad.bo.PersistableBusinessObject;
019    import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
020    
021    import javax.persistence.AttributeOverride;
022    import javax.persistence.AttributeOverrides;
023    import javax.persistence.Column;
024    import javax.persistence.Id;
025    import javax.persistence.JoinColumn;
026    import javax.persistence.JoinColumns;
027    import javax.persistence.OneToMany;
028    import javax.persistence.Table;
029    import java.lang.reflect.Field;
030    import java.util.ArrayList;
031    import java.util.HashMap;
032    import java.util.List;
033    import java.util.Map;
034    
035    /**
036     * This is a description of what this class does - kellerj don't forget to fill this in. 
037     * 
038     * @author Kuali Rice Team (rice.collab@kuali.org)
039     *
040     */
041    public class JpaToDdl {
042    
043            public static void main( String[] args ) throws ClassNotFoundException {
044                    
045                    Class<? extends PersistableBusinessObjectBase> clazz =
046                    (Class<? extends PersistableBusinessObjectBase>) Class.forName(args[0]);
047    
048                    
049                    StringBuffer sb = new StringBuffer( 1000 );
050                    StringBuffer pk = new  StringBuffer();
051                    Table tableAnnotation = (Table)clazz.getAnnotation( Table.class );
052                    
053                    sb.append( "CREATE TABLE " ).append( tableAnnotation.name().toLowerCase() ).append( " (\r\n" );
054    
055                    getClassFields( tableAnnotation.name().toLowerCase(), clazz, sb, pk, null );
056                    pk.append( " )\r\n" );
057                    sb.append( pk );
058                    sb.append( ")\r\n" );
059                    sb.append( "/\r\n" );
060                    System.out.println( sb.toString() );
061                    sb.setLength( 0 );
062                    getReferences( clazz, sb );
063                    System.out.println( sb.toString() );
064            }
065    
066            
067            private static String javaToSqlDataType( Class<? extends Object> dataType ) {
068                    if ( dataType.equals( String.class ) ) {
069                            return "VARCHAR(40)";
070                    } else if (dataType.equals(Long.class) || dataType.equals(Integer.class)) {
071                            return "NUMBER(?,?)";
072                    } else if (dataType.equals(java.util.Date.class) || dataType.equals(java.sql.Date.class)) {
073                            return "DATE";
074                    } else if (dataType.equals(java.sql.Timestamp.class)) {
075                            return "TIMESTAMP";
076                    }
077                    return "VARCHAR(40)";
078            }
079            
080            private static void getClassFields( String tableName, Class<? extends Object> clazz, StringBuffer sb, StringBuffer pk, Map<String,AttributeOverride> overrides ) {
081                    // first get annotation overrides
082                    if ( overrides == null ) {
083                            overrides = new HashMap<String,AttributeOverride>();
084                    }
085                    if ( clazz.getAnnotation( AttributeOverride.class ) != null ) {
086                            AttributeOverride ao = (AttributeOverride)clazz.getAnnotation( AttributeOverride.class );
087                            if ( !overrides.containsKey(ao.name() ) ) {
088                                    overrides.put(ao.name(), ao);
089                            }
090                    }
091                    if ( clazz.getAnnotation( AttributeOverrides.class ) != null ) {
092                            for ( AttributeOverride ao : ((AttributeOverrides)clazz.getAnnotation( AttributeOverrides.class )).value() ) {
093                                    if ( !overrides.containsKey(ao.name() ) ) {
094                                            overrides.put(ao.name(), ao);
095                                    }
096                                    overrides.put(ao.name(),ao);
097                            }
098                    }
099                    for ( Field field : clazz.getDeclaredFields() ) {
100                            Id id = (Id)field.getAnnotation( Id.class );
101                            Column column = (Column)field.getAnnotation( Column.class );
102                            if ( column != null ) {
103                                    sb.append( "\t" );
104                                    if ( field.getName().equals( "objectId" ) ) {
105                                            sb.append( "obj_id\t\tVARCHAR2(36) NOT NULL" );
106                                    } else if ( field.getName().equals( "versionNumber" ) ) {
107                                            sb.append( "ver_nbr\t\tNUMBER(8,0)" );
108                                    } else {
109                                            if ( overrides.containsKey(field.getName() ) ) {
110                                                    sb.append( overrides.get(field.getName()).column().name().toLowerCase() );
111                                            } else {
112                                                    sb.append( column.name().toLowerCase() );
113                                            }
114                                            sb.append( "\t\t" );
115                                            if ( field.getType() == boolean.class ) {
116                                                    sb.append( "VARCHAR2(1) DEFAULT 'Y'" );
117                                            } else {
118                                                    sb.append( javaToSqlDataType( field.getType() ) );
119                                            }
120                                            if ( id != null ) {
121                                                    if ( pk.length() == 0 ) {
122                                                            pk.append( "\tCONSTRAINT " + tableName + "p1 PRIMARY KEY ( " );
123                                                    } else {
124                                                            pk.append( ", " );
125                                                    }
126                                                    if ( overrides.containsKey(field.getName() ) ) {
127                                                            pk.append( overrides.get(field.getName()).column().name().toLowerCase() );
128                                                    } else {
129                                                            pk.append( column.name().toLowerCase() );
130                                                    }
131                                            }
132                                    }
133                                    sb.append( ",\r\n" );
134                            }
135                    }
136                    if ( !clazz.equals( PersistableBusinessObject.class ) && clazz.getSuperclass() != null ) {
137                            getClassFields( tableName, clazz.getSuperclass(), sb, pk, overrides );
138                    }
139            }
140    
141            private static void getReferences( Class<? extends Object> clazz, StringBuffer sb ) {
142                    for ( Field field : clazz.getDeclaredFields() ) {
143                            JoinColumns multiKey = (JoinColumns)field.getAnnotation( JoinColumns.class );
144                            JoinColumn singleKey = (JoinColumn)field.getAnnotation( JoinColumn.class );
145                            if ( multiKey != null || singleKey != null ) {
146                                    List<JoinColumn> keys = new ArrayList<JoinColumn>();
147                                    if ( singleKey != null ) {
148                                            keys.add( singleKey );
149                                    }
150                                    if ( multiKey != null ) {
151                                            for ( JoinColumn col : multiKey.value() ) {
152                                                    keys.add( col );
153                                            }
154                                    }
155                                    OneToMany oneToMany = field.getAnnotation( OneToMany.class );
156                                    if ( oneToMany != null ) {
157                                            sb.append( "ALTER TABLE " );
158                                            sb.append( field.getName() );
159                                            sb.append( "\" element-class-ref=\"" );
160                                            sb.append( oneToMany.targetEntity().getName() );
161                                            sb.append( "\" collection-class=\"org.apache.ojb.broker.util.collections.ManageableArrayList\" auto-retrieve=\"true\" auto-update=\"object\" auto-delete=\"object\" proxy=\"true\">\r\n" );
162                                            for ( JoinColumn col : keys ) {
163                                                    sb.append( "                    <inverse-foreignkey field-ref=\"" );
164                                                    sb.append( getPropertyFromField( clazz, col.name() ) );
165                                                    sb.append( "\" />\r\n" );
166                                            }
167                                            sb.append( "            </collection-descriptor>\r\n" );
168                                    }
169                            }
170                    }
171            }
172            
173            private static String getPropertyFromField( Class<? extends Object> clazz, String colName ) {
174                    for ( Field field : clazz.getDeclaredFields() ) {
175                            Column column = (Column)field.getAnnotation( Column.class );
176                            if ( column != null ) {
177                                    if ( column.name().equals( colName ) ) {
178                                            return field.getName();
179                                    }
180                            }
181                    }
182                    return "";
183            }
184    }