001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/AggregateImpl.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     Aennchenstr. 19
030     53115 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     ---------------------------------------------------------------------------*/
044    package org.deegree.model.spatialschema;
045    
046    import java.io.Serializable;
047    import java.util.ArrayList;
048    import java.util.Iterator;
049    
050    import org.deegree.framework.log.ILogger;
051    import org.deegree.framework.log.LoggerFactory;
052    import org.deegree.model.crs.CoordinateSystem;
053    
054    /**
055     * default implementierung of the Aggregate interface
056     * 
057     * ------------------------------------------------------------
058     * 
059     * @version 8.6.2001
060     * @author Andreas Poth href="mailto:poth@lat-lon.de"
061     */
062    abstract class AggregateImpl extends GeometryImpl implements Aggregate, Serializable {
063    
064        private static ILogger LOG = LoggerFactory.getLogger( AggregateImpl.class );
065    
066        /** Use serialVersionUID for interoperability. */
067        private final static long serialVersionUID = 1161164609227432958L;
068    
069        protected ArrayList<Geometry> aggregate = new ArrayList<Geometry>( 500 );
070    
071        /**
072         * Creates a new AggregateImpl object.
073         * 
074         * @param crs
075         */
076        public AggregateImpl( CoordinateSystem crs ) {
077            super( crs );
078        }
079    
080        /**
081         * Creates a new AggregateImpl object.
082         */
083        private AggregateImpl() {
084            super( null );
085        }
086    
087        /**
088         * returns the number of Geometry within the aggregation
089         */
090        public int getSize() {
091            return aggregate.size();
092        }
093    
094        /**
095         * merges this aggregation with another one
096         * 
097         * @exception GeometryException
098         *                a GeometryException will be thrown if the submitted isn't the same type as the
099         *                recieving one.
100         */
101        public void merge( Aggregate aggregate )
102                                throws GeometryException {
103            if ( !this.getClass().getName().equals( aggregate.getClass().getName() ) ) {
104                throw new GeometryException( "Aggregations are not of the same type!" );
105            }
106    
107            for ( int i = 0; i < this.getSize(); i++ ) {
108                this.add( aggregate.getObjectAt( i ) );
109            }
110    
111            setValid( false );
112        }
113    
114        /**
115         * adds an Geometry to the aggregation
116         */
117        public void add( Geometry gmo ) {
118            aggregate.add( gmo );
119    
120            setValid( false );
121        }
122    
123        /**
124         * inserts a Geometry in the aggregation. all elements with an index equal or larger index will
125         * be moved. if index is larger then getSize() - 1 or smaller then 0 or gmo equals null an
126         * exception will be thrown.
127         * 
128         * @param gmo
129         *            Geometry to insert.
130         * @param index
131         *            position where to insert the new Geometry
132         */
133        public void insertObjectAt( Geometry gmo, int index )
134                                throws GeometryException {
135            if ( ( index < 0 ) || ( index > this.getSize() - 1 ) ) {
136                throw new GeometryException( "invalid index/position: " + index + " to insert a geometry!" );
137            }
138    
139            if ( gmo == null ) {
140                throw new GeometryException( "gmo == null. it isn't possible to insert a value" + " that equals null!" );
141            }
142    
143            aggregate.add( index, gmo );
144    
145            setValid( false );
146        }
147    
148        /**
149         * sets the submitted Geometry at the submitted index. the element at the position
150         * <code>index</code> will be removed. if index is larger then getSize() - 1 or smaller then 0
151         * or gmo equals null an exception will be thrown.
152         * 
153         * @param gmo
154         *            Geometry to set.
155         * @param index
156         *            position where to set the new Geometry
157         */
158        public void setObjectAt( Geometry gmo, int index )
159                                throws GeometryException {
160            if ( ( index < 0 ) || ( index > this.getSize() - 1 ) ) {
161                throw new GeometryException( "invalid index/position: " + index + " to set a geometry!" );
162            }
163    
164            if ( gmo == null ) {
165                throw new GeometryException( "gmo == null. it isn't possible to set a value" + " that equals null!" );
166            }
167    
168            aggregate.set( index, gmo );
169    
170            setValid( false );
171        }
172    
173        /**
174         * removes the submitted Geometry from the aggregation
175         * 
176         * @return the removed Geometry
177         */
178        public Geometry removeObject( Geometry gmo ) {
179            if ( gmo == null ) {
180                return null;
181            }
182    
183            int i = aggregate.indexOf( gmo );
184    
185            Geometry gmo_ = null;
186    
187            try {
188                gmo_ = removeObjectAt( i );
189            } catch ( GeometryException e ) {
190                LOG.logError( e.getMessage(), e );
191            }
192    
193            setValid( false );
194    
195            return gmo_;
196        }
197    
198        /**
199         * removes the Geometry at the submitted index from the aggregation. if index is larger then
200         * getSize() - 1 or smaller then 0 an exception will be thrown.
201         * 
202         * @return the removed Geometry
203         */
204        public Geometry removeObjectAt( int index )
205                                throws GeometryException {
206            if ( index < 0 ) {
207                return null;
208            }
209    
210            if ( index > ( this.getSize() - 1 ) ) {
211                throw new GeometryException( "invalid index/position: " + index + " to remove a geometry!" );
212            }
213    
214            Geometry gmo = aggregate.remove( index );
215    
216            setValid( false );
217    
218            return gmo;
219        }
220    
221        /**
222         * removes all Geometry from the aggregation.
223         */
224        public void removeAll() {
225            aggregate.clear();
226            envelope = null;
227            setValid( false );
228        }
229    
230        /**
231         * returns the Geometry at the submitted index. if index is larger then getSize() - 1 or smaller
232         * then 0 an exception will be thrown.
233         */
234        public Geometry getObjectAt( int index ) {
235            return aggregate.get( index );
236        }
237    
238        /**
239         * returns all Geometries as array
240         */
241        public Geometry[] getAll() {
242            Geometry[] gmos = new Geometry[this.getSize()];
243    
244            return aggregate.toArray( gmos );
245        }
246    
247        /**
248         * returns true if the submitted Geometry is within the aggregation
249         */
250        public boolean isMember( Geometry gmo ) {
251            return aggregate.contains( gmo );
252        }
253    
254        /**
255         * returns the aggregation as an iterator
256         */
257        public Iterator getIterator() {
258            return aggregate.iterator();
259        }
260    
261        /**
262         * returns true if no geometry stored within the collection.
263         */
264        public boolean isEmpty() {
265            return ( getSize() == 0 );
266        }
267    
268        /**
269         * sets the spatial reference system
270         * 
271         * @param crs
272         *            new spatial reference system
273         */
274        public void setCoordinateSystem( CoordinateSystem crs ) {
275            super.setCoordinateSystem( crs );
276    
277            if ( aggregate != null ) {
278                for ( int i = 0; i < aggregate.size(); i++ ) {
279                    ( (GeometryImpl) getObjectAt( i ) ).setCoordinateSystem( crs );
280                }
281                setValid( false );
282            }
283        }
284    
285        /**
286         * translate the point by the submitted values. the <code>dz</code>- value will be ignored.
287         */
288        public void translate( double[] d ) {
289            try {
290                for ( int i = 0; i < getSize(); i++ ) {
291                    Geometry gmo = getObjectAt( i );
292                    gmo.translate( d );
293                }
294                setValid( false );
295            } catch ( Exception e ) {
296                LOG.logError( e.getMessage(), e );
297            }
298            setValid( false );
299        }
300    
301        /**
302         * 
303         * 
304         * @param other
305         * 
306         * @return
307         */
308        public boolean equals( Object other ) {
309            if ( envelope == null ) {
310                calculateParam();
311            }
312            if ( !super.equals( other ) || !( other instanceof AggregateImpl )
313                 || !envelope.equals( ( (Geometry) other ).getEnvelope() )
314                 || ( getSize() != ( (Aggregate) other ).getSize() ) ) {
315                return false;
316            }
317    
318            try {
319                for ( int i = 0; i < getSize(); i++ ) {
320                    Object o1 = getObjectAt( i );
321                    Object o2 = ( (Aggregate) other ).getObjectAt( i );
322    
323                    if ( !o1.equals( o2 ) ) {
324                        return false;
325                    }
326                }
327            } catch ( Exception ex ) {
328                return false;
329            }
330    
331            return true;
332        }
333    
334        /**
335         * The Boolean valued operation "intersects" shall return TRUE if this Geometry intersects
336         * another Geometry. Within a Complex, the Primitives do not intersect one another. In general,
337         * topologically structured data uses shared geometric objects to capture intersection
338         * information.
339         */
340        public boolean intersects( Geometry gmo ) {
341            boolean inter = false;
342    
343            try {
344                for ( int i = 0; i < aggregate.size(); i++ ) {
345                    if ( this.getObjectAt( i ).intersects( gmo ) ) {
346                        inter = true;
347                        break;
348                    }
349                }
350            } catch ( Exception e ) {
351            }
352    
353            return inter;
354        }
355    
356        /**
357         * 
358         * 
359         * @return
360         */
361        public String toString() {
362            String ret = null;
363            ret = "aggregate = " + aggregate + "\n";
364            ret += ( "envelope = " + envelope + "\n" );
365            return ret;
366        }
367    }