Coverage Report - org.apache.ojb.broker.metadata.torque.TorqueForeignKeyGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
TorqueForeignKeyGenerator
N/A
N/A
2.533
 
 1  
 package org.apache.ojb.broker.metadata.torque;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 19  
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 20  
 import org.apache.ojb.broker.metadata.DescriptorRepository;
 21  
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 22  
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
 23  
 import org.apache.ojb.broker.util.logging.Logger;
 24  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 25  
 
 26  
 import java.util.HashMap;
 27  
 import java.util.Iterator;
 28  
 import java.util.Vector;
 29  
 
 30  
 public class TorqueForeignKeyGenerator {
 31  
         private final Logger logger = LoggerFactory.getLogger(this.getClass());
 32  
     private DescriptorRepository repository;
 33  
     private HashMap mappingTables = new HashMap();
 34  
     private HashMap foreignKeyVectors = new HashMap();
 35  
 
 36  
     public TorqueForeignKeyGenerator(DescriptorRepository repository) {
 37  
         this.repository = repository;
 38  
     }
 39  
 
 40  
     public void buildConstraintsMap() {
 41  
         Iterator classDescriptorIterators = this.repository.iterator();
 42  
         while (classDescriptorIterators.hasNext()) {
 43  
             ClassDescriptor cd = (ClassDescriptor) classDescriptorIterators.next();
 44  
             if(cd.isAbstract() || cd.isInterface())
 45  
             {
 46  
                                 logger.debug( "Skip constraint build for abstract class/ interface " + cd.getClassNameOfObject() );
 47  
             }
 48  
             else
 49  
             {
 50  
                 buildConstraints(cd);
 51  
                 buildOneToOneConstraints(cd);
 52  
             }
 53  
         }
 54  
     }
 55  
 
 56  
     public Vector getForeignKeysForTable(String tableName) {
 57  
         return (Vector) this.foreignKeyVectors.get(tableName);
 58  
     }
 59  
 
 60  
     public HashMap getMappingTables() {
 61  
         return this.mappingTables;
 62  
     }
 63  
 
 64  
     private void buildTableFieldDescriptors(FieldDescriptor fieldDescriptors[], TableDescriptor tableDescriptor) {
 65  
         for (int i = 0; i < fieldDescriptors.length; i++) {
 66  
             tableDescriptor.addColumn(fieldDescriptors[i]);
 67  
         }
 68  
     }
 69  
 
 70  
     private void buildConstraints(ClassDescriptor cd) {
 71  
         Vector collectionDescriptors = cd.getCollectionDescriptors();
 72  
         for (int i = 0; i < collectionDescriptors.size(); i++) {
 73  
             CollectionDescriptor collectionDescriptor = (CollectionDescriptor) collectionDescriptors.get(i);
 74  
             if (collectionDescriptor.isMtoNRelation()) {
 75  
                 buildManyToManyConstraints(cd, collectionDescriptor);
 76  
             } else {
 77  
                 buildOneToManyReferences(cd, collectionDescriptor);
 78  
             }
 79  
         }
 80  
     }
 81  
 
 82  
     private void buildManyToManyConstraints(ClassDescriptor cd, CollectionDescriptor collectionDescriptor) {
 83  
         Vector columns = new Vector();
 84  
 
 85  
         ClassDescriptor itemDescriptor = this.repository.getDescriptorFor(collectionDescriptor.getItemClass());
 86  
         buildManyToManyReferences(cd, collectionDescriptor, collectionDescriptor.getFksToThisClass(), columns);
 87  
         buildManyToManyReferences(itemDescriptor, collectionDescriptor, collectionDescriptor.getFksToItemClass(), columns);
 88  
 
 89  
         if (isImplicitlyMapped(collectionDescriptor.getIndirectionTable())) {
 90  
             TableDescriptor mappingTable = new TableDescriptor();
 91  
             buildTableFieldDescriptors((FieldDescriptor[]) columns.toArray(new FieldDescriptor[0]), mappingTable);
 92  
             mappingTable.setName(collectionDescriptor.getIndirectionTable());
 93  
             this.mappingTables.put(mappingTable.getName(), mappingTable);
 94  
         }
 95  
     }
 96  
 
 97  
     private void buildManyToManyReferences(ClassDescriptor cd, CollectionDescriptor collectionDescriptor,
 98  
                                            Object keys[], Vector columns)
 99  
     {
 100  
         if(cd.isAbstract() || cd.isInterface())
 101  
         {
 102  
                         logger.debug( "Skip foreign key build for MtoM, found abstract base class or interface " + cd.getClassNameOfObject() );
 103  
             return;
 104  
         }
 105  
         StringBuffer buffer = new StringBuffer(256);
 106  
         buildForeignKeyHeader(cd.getFullTableName(), buffer);
 107  
 
 108  
         for (int i = 0; i < keys.length; i++) {
 109  
             String columnName = (String) keys[i];
 110  
 
 111  
             FieldDescriptor foreignColumn = cd.getPkFields()[i];
 112  
             String foreignColumnName = foreignColumn.getPersistentField().getName();
 113  
             buildReferenceForColumn(buffer, columnName, foreignColumnName);
 114  
             FieldDescriptor fieldDescriptor = (FieldDescriptor)foreignColumn.clone();
 115  
             fieldDescriptor.setColumnName(columnName);
 116  
             columns.add(fieldDescriptor);
 117  
         }
 118  
         buffer.append("        </foreign-key>\n");
 119  
 
 120  
         addReferenceToTable(collectionDescriptor.getIndirectionTable(), buffer.toString());
 121  
     }
 122  
 
 123  
     private void buildOneToManyReferences(ClassDescriptor cd, CollectionDescriptor collectionDescriptor) {
 124  
         Vector foreignKeyIndices = collectionDescriptor.getForeignKeyFields();
 125  
         ClassDescriptor foreignKeyClassDescriptor = this.repository.getDescriptorFor(collectionDescriptor.getItemClass());
 126  
         buildForeignKey(cd, foreignKeyIndices, foreignKeyClassDescriptor);
 127  
     }
 128  
 
 129  
 
 130  
     private void buildOneToOneConstraints(ClassDescriptor classDescriptor) {
 131  
         Vector referenceDescriptors = classDescriptor.getObjectReferenceDescriptors();
 132  
         for (int i = 0; i < referenceDescriptors.size(); i++) {
 133  
             ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) referenceDescriptors.get(i);
 134  
 
 135  
             Vector foreignKeyIndices = ord.getForeignKeyFields();
 136  
             ClassDescriptor foreignClassDescriptor = this.repository.getDescriptorFor(ord.getItemClass());
 137  
             buildForeignKey(foreignClassDescriptor, foreignKeyIndices, classDescriptor);
 138  
         }
 139  
     }
 140  
 
 141  
     private void buildForeignKey(ClassDescriptor foreignClassDescriptor, Vector foreignKeyIndices, ClassDescriptor classDescriptor) {
 142  
 
 143  
         if(classDescriptor.isAbstract() || classDescriptor.isInterface())
 144  
         {
 145  
                         logger.debug( "Skip foreign key build, found abstract base class or interface " + classDescriptor.getClassNameOfObject() );
 146  
             return;
 147  
         }
 148  
         StringBuffer buffer = new StringBuffer(256);
 149  
         buildForeignKeyHeader(foreignClassDescriptor.getFullTableName(), buffer);
 150  
 
 151  
         for (int i = 0; i < foreignKeyIndices.size(); i++) {
 152  
             String columnName = null;
 153  
             Object obj = foreignKeyIndices.get(i);
 154  
 
 155  
             if (obj instanceof Integer)
 156  
             {
 157  
                 int foreignKeyIndex = ((Integer) obj).intValue();
 158  
                 columnName = classDescriptor.getFieldDescriptorByIndex(foreignKeyIndex).getColumnName();
 159  
             }
 160  
             else
 161  
             {
 162  
                     FieldDescriptor fld = classDescriptor.getFieldDescriptorByName((String) obj);
 163  
                     if(fld == null)
 164  
                     {
 165  
                                                 logger.debug( "FieldDescriptor for foreign key parameter \n" + obj + " was not found in ClassDescriptor \n" + classDescriptor );
 166  
                     }
 167  
                     else columnName = fld.getColumnName();
 168  
             }
 169  
 
 170  
             FieldDescriptor foreignColumn = foreignClassDescriptor.getPkFields()[i];
 171  
             String foreignColumnName = foreignColumn.getColumnName();
 172  
             buildReferenceForColumn(buffer, columnName, foreignColumnName);
 173  
         }
 174  
         buffer.append("        </foreign-key>\n");
 175  
         addReferenceToTable(classDescriptor.getFullTableName(), buffer.toString());
 176  
     }
 177  
 
 178  
     private void buildForeignKeyHeader(String foreignClassName, StringBuffer buffer) {
 179  
         buffer.append("        <foreign-key foreignTable=\"");
 180  
         buffer.append(foreignClassName);
 181  
         buffer.append("\">\n");
 182  
     }
 183  
 
 184  
     private void buildReferenceForColumn(StringBuffer buffer, String columnName, String foreignColumnName) {
 185  
         buffer.append("            <reference local=\"");
 186  
         buffer.append(columnName);
 187  
         buffer.append("\" foreign=\"");
 188  
         buffer.append(foreignColumnName);
 189  
         buffer.append("\"/>\n");
 190  
     }
 191  
 
 192  
 
 193  
     private boolean isImplicitlyMapped(String tableName) {
 194  
         Iterator classDescriptorIterator = repository.iterator();
 195  
 
 196  
         while (classDescriptorIterator.hasNext()) {
 197  
             ClassDescriptor cd = (ClassDescriptor) classDescriptorIterator.next();
 198  
             if (tableName.equals(cd.getFullTableName())) {
 199  
                 return false;
 200  
             }
 201  
         }
 202  
 
 203  
         return true;
 204  
     }
 205  
 
 206  
     private void addReferenceToTable(String tableName, String reference) {
 207  
         Vector tableReferences = (Vector) this.foreignKeyVectors.get(tableName);
 208  
         if (tableReferences == null) {
 209  
             tableReferences = new Vector();
 210  
             this.foreignKeyVectors.put(tableName, tableReferences);
 211  
 
 212  
         }
 213  
         if (!tableReferences.contains(reference)) {
 214  
             tableReferences.add(reference);
 215  
         }
 216  
     }
 217  
 }