001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/io/datastore/sql/transaction/delete/TableNode.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.io.datastore.sql.transaction.delete;
037    
038    import java.util.Collection;
039    import java.util.HashMap;
040    import java.util.HashSet;
041    import java.util.Map;
042    import java.util.Set;
043    
044    import org.deegree.io.datastore.FeatureId;
045    import org.deegree.io.datastore.schema.content.MappingField;
046    import org.deegree.ogcwebservices.wfs.operation.transaction.Delete;
047    
048    /**
049     * Represents a table row that has to be deleted as part of a {@link Delete} operation.
050     * <p>
051     * Connected table entries (rows that refer to this row or that are referenced by this row) are also
052     * stored.
053     *
054     * @see TableGraph
055     *
056     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
057     * @author last edited by: $Author: mschneider $
058     *
059     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $
060     */
061    public class TableNode {
062    
063        private String table;
064    
065        private Map<String, KeyColumn> namesToColumns = new HashMap<String, KeyColumn>();
066    
067        private Set<TableNode> preNodes = new HashSet<TableNode>();
068    
069        private Set<TableNode> postNodes = new HashSet<TableNode>();
070    
071        private boolean deleteVetoPossible;
072    
073        /**
074         * Creates a new <code>DeleteNode</code> instance.
075         *
076         * @param table
077         * @param keyColumns
078         */
079        TableNode( String table, Collection<KeyColumn> keyColumns ) {
080            this.table = table;
081            for ( KeyColumn column : keyColumns ) {
082                this.namesToColumns.put( column.getName(), column );
083            }
084        }
085    
086        /**
087         * Creates a new <code>DeleteNode</code> instance for a feature instance.
088         *
089         * @param fid
090         */
091        TableNode( FeatureId fid ) {
092            MappingField[] fidFields = fid.getFidDefinition().getIdFields();
093            for ( int i = 0; i < fidFields.length; i++ ) {
094                KeyColumn column = new KeyColumn( fidFields[i].getField(), fidFields[i].getType(), fid.getValue( i ) );
095                this.namesToColumns.put( column.getName(), column );
096            }
097            this.table = fid.getFeatureType().getTable();
098        }
099    
100        boolean isDeleteVetoPossible() {
101            return this.deleteVetoPossible;
102        }
103    
104        void setDeleteVetoPossible() {
105            this.deleteVetoPossible = true;
106        }
107    
108        /**
109         * Returns the table name.
110         *
111         * @return the table name
112         */
113        String getTable() {
114            return this.table;
115        }
116    
117        /**
118         * Returns the key columns that identify the table row.
119         *
120         * @return the key columns that identify the table row
121         */
122        Collection<KeyColumn> getKeyColumns() {
123            return this.namesToColumns.values();
124        }
125    
126        /**
127         * Returns the value for the given key column name.
128         *
129         * @param columnName
130         * @return the value for the given key column name
131         */
132        KeyColumn getKeyColumnValue( String columnName ) {
133            return this.namesToColumns.get( columnName );
134        }
135    
136        /**
137         * Returns the set of post nodes, i.e. table rows that <i>are referenced</i> by this row.
138         *
139         * @return the set of post nodes
140         */
141        Collection<TableNode> getPostNodes() {
142            return this.postNodes;
143        }
144    
145        /**
146         * Returns the set of pre nodes, i.e. table rows that <i>refer</i> to this row.
147         *
148         * @return the set of pre nodes
149         */
150        Collection<TableNode> getPreNodes() {
151            return this.preNodes;
152        }
153    
154        /**
155         * Connects this node to the given target node.
156         * <p>
157         * NOTE: The target node is the one that stores the primary key.
158         *
159         * @param targetNode
160         */
161        void connect( TableNode targetNode ) {
162            if ( !this.postNodes.contains( targetNode ) ) {
163                this.postNodes.add( targetNode );
164                targetNode.preNodes.add( this );
165            }
166        }
167    
168        @Override
169        public int hashCode() {
170            return this.table.hashCode();
171        }
172    
173        @Override
174        public boolean equals( Object obj ) {
175            if ( obj == null || !( obj instanceof TableNode ) ) {
176                return false;
177            }
178            TableNode that = (TableNode) obj;
179            if ( !this.table.equals( that.table ) ) {
180                return false;
181            }
182            if ( this.namesToColumns.size() != that.namesToColumns.size() ) {
183                return false;
184            }
185            for ( String columnName : this.namesToColumns.keySet() ) {
186                KeyColumn thisKeyValue = this.namesToColumns.get( columnName );
187                KeyColumn thatKeyValue = that.namesToColumns.get( columnName );
188                if ( !thisKeyValue.equals( thatKeyValue ) ) {
189                    return false;
190                }
191            }
192            return true;
193        }
194    
195        @Override
196        public String toString() {
197            StringBuffer sb = new StringBuffer();
198            sb.append( this.table );
199            for ( KeyColumn column : this.namesToColumns.values() ) {
200                sb.append( "," );
201                sb.append( column );
202            }
203            return sb.toString();
204        }
205    
206        String toString( String indent, Set<TableNode> printedNodes ) {
207            StringBuffer sb = new StringBuffer();
208            sb.append( indent );
209            sb.append( "- table: " );
210            sb.append( this.table );
211            for ( KeyColumn column : this.namesToColumns.values() ) {
212                sb.append( ", " );
213                sb.append( column );
214            }
215            sb.append( '\n' );
216    
217            for ( TableNode postNode : this.postNodes ) {
218                sb.append( indent );
219                if ( printedNodes.contains( postNode ) ) {
220                    sb.append( indent + " " );
221                    sb.append( "- table: " );
222                    sb.append( postNode.getTable() );
223                    sb.append( " (DUP)\n" );
224                } else {
225                    printedNodes.add( postNode );
226                    sb.append( postNode.toString( indent + " ", printedNodes ) );
227                }
228            }
229            return sb.toString();
230        }
231    
232    }
233    
234    /**
235     * Encapsulates a column name, it's type code and a value.
236     */
237    class KeyColumn {
238    
239        private String name;
240    
241        private int typeCode;
242    
243        private Object value;
244    
245        KeyColumn( String name, int typeCode, Object value ) {
246            this.name = name;
247            this.typeCode = typeCode;
248            this.value = value;
249        }
250    
251        String getName() {
252            return this.name;
253        }
254    
255        int getTypeCode() {
256            return this.typeCode;
257        }
258    
259        Object getValue() {
260            return this.value;
261        }
262    
263        @Override
264        public boolean equals( Object obj ) {
265            if ( obj == null || !( obj instanceof KeyColumn ) ) {
266                return false;
267            }
268            KeyColumn that = (KeyColumn) obj;
269            if ( !this.name.equals( that.name ) ) {
270                return false;
271            }
272            return this.value.equals( that.value );
273        }
274    
275        @Override
276        public String toString() {
277            StringBuffer sb = new StringBuffer();
278            sb.append( this.name );
279            sb.append( '=' );
280            sb.append( this.value );
281            return sb.toString();
282        }
283    }