001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/datastore/sql/transaction/delete/TableNode.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     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.sql.transaction.delete;
044    
045    import java.util.Collection;
046    import java.util.HashMap;
047    import java.util.HashSet;
048    import java.util.Map;
049    import java.util.Set;
050    
051    import org.deegree.io.datastore.FeatureId;
052    import org.deegree.io.datastore.schema.content.MappingField;
053    import org.deegree.ogcwebservices.wfs.operation.transaction.Delete;
054    
055    /**
056     * Represents a table row that has to be deleted as part of a {@link Delete} operation.
057     * <p>
058     * Connected table entries (rows that refer to this row or that are referenced by this row) are also
059     * stored.
060     * 
061     * @see TableGraph
062     * 
063     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
064     * @author last edited by: $Author: apoth $
065     * 
066     * @version $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
067     */
068    public class TableNode {
069    
070        private String table;
071    
072        private Map<String, KeyColumn> namesToColumns = new HashMap<String, KeyColumn>();
073    
074        private Set<TableNode> preNodes = new HashSet<TableNode>();
075    
076        private Set<TableNode> postNodes = new HashSet<TableNode>();
077    
078        private boolean deleteVetoPossible;
079    
080        /**
081         * Creates a new <code>DeleteNode</code> instance.
082         * 
083         * @param table
084         * @param keyColumns
085         */
086        TableNode( String table, Collection<KeyColumn> keyColumns ) {
087            this.table = table;
088            for ( KeyColumn column : keyColumns ) {
089                this.namesToColumns.put( column.getName(), column );
090            }
091        }
092    
093        /**
094         * Creates a new <code>DeleteNode</code> instance for a feature instance.
095         * 
096         * @param fid
097         */
098        TableNode( FeatureId fid ) {
099            MappingField[] fidFields = fid.getFidDefinition().getIdFields();
100            for ( int i = 0; i < fidFields.length; i++ ) {
101                KeyColumn column = new KeyColumn( fidFields[i].getField(), fidFields[i].getType(), fid.getValue( i ) );
102                this.namesToColumns.put( column.getName(), column );
103            }
104            this.table = fid.getFeatureType().getTable();
105        }
106    
107        boolean isDeleteVetoPossible() {
108            return this.deleteVetoPossible;
109        }
110    
111        void setDeleteVetoPossible() {
112            this.deleteVetoPossible = true;
113        }
114    
115        /**
116         * Returns the table name.
117         * 
118         * @return the table name
119         */
120        String getTable() {
121            return this.table;
122        }
123    
124        /**
125         * Returns the key columns that identify the table row.
126         * 
127         * @return the key columns that identify the table row
128         */
129        Collection<KeyColumn> getKeyColumns() {
130            return this.namesToColumns.values();
131        }
132    
133        /**
134         * Returns the value for the given key column name.
135         * 
136         * @param columnName
137         * @return the value for the given key column name
138         */
139        KeyColumn getKeyColumnValue( String columnName ) {
140            return this.namesToColumns.get( columnName );
141        }
142    
143        /**
144         * Returns the set of post nodes, i.e. table rows that <i>are referenced</i> by this row.
145         * 
146         * @return the set of post nodes
147         */
148        Collection<TableNode> getPostNodes() {
149            return this.postNodes;
150        }
151    
152        /**
153         * Returns the set of pre nodes, i.e. table rows that <i>refer</i> to this row.
154         * 
155         * @return the set of pre nodes
156         */
157        Collection<TableNode> getPreNodes() {
158            return this.preNodes;
159        }
160    
161        /**
162         * Connects this node to the given target node.
163         * <p>
164         * NOTE: The target node is the one that stores the primary key.
165         * 
166         * @param targetNode
167         */
168        void connect( TableNode targetNode ) {
169            if ( !this.postNodes.contains( targetNode ) ) {
170                this.postNodes.add( targetNode );
171                targetNode.preNodes.add( this );
172            }
173        }
174    
175        @Override
176        public int hashCode() {
177            return this.table.hashCode();
178        }
179    
180        @Override
181        public boolean equals( Object obj ) {
182            if ( obj == null || !( obj instanceof TableNode ) ) {
183                return false;
184            }
185            TableNode that = (TableNode) obj;
186            if ( !this.table.equals( that.table ) ) {
187                return false;
188            }
189            if ( this.namesToColumns.size() != that.namesToColumns.size() ) {
190                return false;
191            }
192            for ( String columnName : this.namesToColumns.keySet() ) {
193                KeyColumn thisKeyValue = this.namesToColumns.get( columnName );
194                KeyColumn thatKeyValue = that.namesToColumns.get( columnName );
195                if ( !thisKeyValue.equals( thatKeyValue ) ) {
196                    return false;
197                }
198            }
199            return true;
200        }
201    
202        @Override
203        public String toString() {
204            StringBuffer sb = new StringBuffer();
205            sb.append( this.table );
206            for ( KeyColumn column : this.namesToColumns.values() ) {
207                sb.append( "," );
208                sb.append( column );
209            }
210            return sb.toString();
211        }
212    
213        String toString( String indent, Set<TableNode> printedNodes ) {
214            StringBuffer sb = new StringBuffer();
215            sb.append( indent );
216            sb.append( "- table: " );
217            sb.append( this.table );
218            for ( KeyColumn column : this.namesToColumns.values() ) {
219                sb.append( ", " );
220                sb.append( column );
221            }
222            sb.append( '\n' );
223    
224            for ( TableNode postNode : this.postNodes ) {
225                sb.append( indent );
226                if ( printedNodes.contains( postNode ) ) {
227                    sb.append( indent + " " );
228                    sb.append( "- table: " );
229                    sb.append( postNode.getTable() );
230                    sb.append( " (DUP)\n" );
231                } else {
232                    printedNodes.add( postNode );
233                    sb.append( postNode.toString( indent + " ", printedNodes ) );
234                }
235            }
236            return sb.toString();
237        }
238    
239    }
240    
241    /**
242     * Encapsulates a column name, it's type code and a value.
243     */
244    class KeyColumn {
245    
246        private String name;
247    
248        private int typeCode;
249    
250        private Object value;
251    
252        KeyColumn( String name, int typeCode, Object value ) {
253            this.name = name;
254            this.typeCode = typeCode;
255            this.value = value;
256        }
257    
258        String getName() {
259            return this.name;
260        }
261    
262        int getTypeCode() {
263            return this.typeCode;
264        }
265    
266        Object getValue() {
267            return this.value;
268        }
269    
270        @Override
271        public boolean equals( Object obj ) {
272            if ( obj == null || !( obj instanceof KeyColumn ) ) {
273                return false;
274            }
275            KeyColumn that = (KeyColumn) obj;
276            if ( !this.name.equals( that.name ) ) {
277                return false;
278            }
279            return this.value.equals( that.value );
280        }
281    
282        @Override
283        public String toString() {
284            StringBuffer sb = new StringBuffer();
285            sb.append( this.name );
286            sb.append( '=' );
287            sb.append( this.value );
288            return sb.toString();
289        }
290    }