001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/datastore/schema/TableRelation.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstraße 19
030     53177 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041     
042     ---------------------------------------------------------------------------*/
043    package org.deegree.io.datastore.schema;
044    
045    import org.deegree.io.datastore.DatastoreTransaction;
046    import org.deegree.io.datastore.idgenerator.IdGenerationException;
047    import org.deegree.io.datastore.idgenerator.IdGenerator;
048    import org.deegree.io.datastore.schema.content.MappingField;
049    
050    /**
051     * Describes a relation (join condition) between two database tables.
052     * 
053     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
054     * @author last edited by: $Author: apoth $
055     * 
056     * @version $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
057     */
058    public class TableRelation {
059    
060        /**
061         * Used to represent the foreign key position.
062         */
063        public static enum FK_INFO {
064            
065            /**
066             * No foreign key information available (sufficient for read access).
067             */
068            noFKInfo,
069            
070            /**
071             * Foreign stored in 'To'-table, primary key in 'From'-table.
072             */
073            fkIsToField,
074            
075            /**
076             * Foreign stored in 'From'-table, primary key in 'To'-table.
077             */
078            fkIsFromField
079        }    
080       
081        private MappingField[] fromFields;
082    
083        private MappingField[] toFields;
084    
085        private FK_INFO fkInfo;
086        
087        private IdGenerator idGenerator;
088    
089        /**
090         * Initializes a newly created <code>TableRelation</code> instance with the given
091         * parameters. 
092         *  
093         * @param fromFields
094         * @param toFields
095         * @param fkInfo
096         * @param idGenerator
097         */
098        public TableRelation( MappingField[] fromFields, MappingField[] toFields, FK_INFO fkInfo,
099                             IdGenerator idGenerator ) {
100            if ( fromFields.length < 1 ) {
101                throw new IllegalArgumentException(
102                    "A relation between two tables must have at least one 'from' field." );
103            }
104            if ( toFields.length < 1 ) {
105                throw new IllegalArgumentException(
106                    "A relation between two tables must have at least one 'to' field." );
107            }
108            if ( fromFields.length != toFields.length ) {
109                throw new IllegalArgumentException(
110                    "A relation between two tables must have the same number of 'from' and 'to' fields." );
111            }
112            this.fromFields = fromFields;
113            this.toFields = toFields;
114            this.fkInfo = fkInfo;
115            this.idGenerator = idGenerator;
116        }
117    
118        /**
119         * Returns the name of the table where the relation starts ('From'-table).
120         * 
121         * @return the name of the table where the relation starts ('From'-table)
122         */
123        public String getFromTable() {
124            return fromFields[0].getTable();
125        }
126    
127        /**
128         * Returns the name of the table where the relation ends ('To'-table).
129         * 
130         * @return the name of the table where the relation ends ('To'-table)
131         */    
132        public String getToTable() {
133            return toFields[0].getTable();
134        }    
135    
136        /**
137         * Returns the {@link MappingField}s that constitute the key in the 'From'-table.
138         *  
139         * @return the MappingFields that constitute the key in the 'From'-table
140         */
141        public MappingField [] getFromFields () {
142            return this.fromFields;
143        }
144    
145        /**
146         * Returns the {@link MappingField}s that constitute the key in the 'To'-table.
147         *  
148         * @return the MappingFields that constitute the key in the 'To'-table
149         */    
150        public MappingField [] getToFields () {
151            return this.toFields;
152        }    
153    
154        /**
155         * Returns the foreign key position.
156         * 
157         * @return the foreign key position
158         */
159        public FK_INFO getFKInfo () {
160            return this.fkInfo;
161        }
162    
163        /**
164         * Returns whether the foreign key is stored in the 'From'-table.
165         * 
166         * @return true, if foreign key information is available and foreign key is in 'From'-table,
167         *         false otherwise
168         */
169        public boolean isFromFK() {
170            boolean isFromFK = false;
171            switch (this.fkInfo) {
172            case fkIsFromField: {
173                isFromFK = true;
174                break;
175            }
176            case fkIsToField: {
177                isFromFK = false;
178                break;
179            }
180            default: {
181                throw new RuntimeException( "No foreign key information available for relation: "
182                    + this );
183            }
184            }
185            return isFromFK;
186        }
187    
188    
189        /**
190         * Returns the {@link IdGenerator} instance that may be used to generate new primary keys.
191         * 
192         * @return IdGenerator instance that may be used to generate new primary keys
193         */
194        public IdGenerator getIdGenerator () {
195            return this.idGenerator;
196        }
197        
198        /**
199         * Returns a new primary key generated by the associated {@link IdGenerator}.
200         * 
201         * @param ta
202         * @return a new primary key
203         * @throws IdGenerationException
204         */
205        public Object getNewPK( DatastoreTransaction ta ) throws IdGenerationException {
206            return this.idGenerator.getNewId( ta );
207        }
208        
209        @Override
210        public String toString() {
211            StringBuffer sb = new StringBuffer();
212            sb.append( getFromTable() );
213            if (this.fkInfo == FK_INFO.fkIsFromField) {
214                sb.append(" (fk) ");
215            }
216            sb.append( " -> " );
217            sb.append( getToTable() );
218            if (this.fkInfo == FK_INFO.fkIsToField) {
219                sb.append(" (fk) ");
220            }        
221            sb.append( " (" );
222            for (int i = 0; i < fromFields.length; i++) {
223                sb.append( fromFields[i] );
224                sb.append( "=" );
225                sb.append( toFields[i] );
226                if ( i != fromFields.length - 1 ) {
227                    sb.append( " AND " );
228                }
229            }
230            sb.append( ")" );
231            return sb.toString();
232        }
233    }