    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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    }