001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/portal/context/MapModel.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.portal.context;
037    
038    import java.util.ArrayList;
039    import java.util.Collections;
040    import java.util.List;
041    
042    import org.deegree.portal.PortalException;
043    
044    /**
045     * TODO add class documentation here
046     * 
047     * @author <a href="mailto:name@deegree.org">Andreas Poth</a>
048     * @author last edited by: $Author: apoth $
049     * 
050     * @version $Revision: 21671 $, $Date: 2009-12-29 09:43:44 +0100 (Di, 29 Dez 2009) $
051     */
052    public class MapModel {
053    
054        private List<LayerGroup> layerGroups;
055    
056        /**
057         * 
058         * @param layerGroups
059         */
060        public void setLayerGroups( List<LayerGroup> layerGroups ) {
061            this.layerGroups = layerGroups;
062        }
063    
064        /**
065         * @return the layerGroups
066         */
067        public List<LayerGroup> getLayerGroups() {
068            return layerGroups;
069        }
070    
071        /**
072         * 
073         * @param action
074         * @return list of {@link Layer} selected for the passed action
075         */
076        public List<MMLayer> getLayersSelectedForAction( String action ) {
077            List<MMLayer> tmp = new ArrayList<MMLayer>();
078            getLayersForAction( layerGroups, action, tmp );
079            return Collections.unmodifiableList( tmp );
080        }
081    
082        private void getLayersForAction( List<LayerGroup> lgs, String action, List<MMLayer> collector ) {
083            for ( LayerGroup layerGroup : lgs ) {
084                List<MMLayer> mapModelEntries = layerGroup.getLayers();
085                for ( MMLayer mapModelEntrry : mapModelEntries ) {
086                    if ( mapModelEntrry.getSelectedFor().contains( action ) ) {
087                        collector.add( mapModelEntrry );
088                    }
089                }
090                getLayersForAction( layerGroup.getLayerGroups(), action, collector );
091            }
092        }
093    
094        /**
095         * 
096         * @param mapModelEntry
097         *            {@link MapModelEntry} to be inserted
098         * @param parent
099         *            if <code>null</code> root node of layertree will be used as parent
100         * @param antecessor
101         *            if <code>null</code> layer will be inserted directly underneath its parent
102         * @param first
103         *            if true layer will be inserted as first layer of a group if antecessor == null
104         * @throws Exception
105         */
106        public void insert( final MapModelEntry mapModelEntry, LayerGroup parent, MapModelEntry antecessor, boolean first )
107                                throws Exception {
108    
109            // check if layer already exists in map model
110            walkLayerTree( new MapModelVisitor() {
111    
112                public void visit( MMLayer layer )
113                                        throws Exception {
114                    if ( layer.getIdentifier().equals( mapModelEntry.getIdentifier() ) ) {
115                        throw new PortalException( "layer: " + layer.getTitle() + " already contained in tree" );
116                    }
117                }
118    
119                public void visit( LayerGroup layerGroup )
120                                        throws Exception {
121                    if ( layerGroup.getIdentifier().equals( mapModelEntry.getIdentifier() ) ) {
122                        throw new PortalException( "layergroup: " + layerGroup.getTitle() + " already contained in tree" );
123                    }
124                }
125    
126            } );
127    
128            if ( mapModelEntry instanceof MMLayer ) {
129                insertLayer( (MMLayer) mapModelEntry, parent, antecessor, first );
130            } else if ( mapModelEntry instanceof LayerGroup ) {
131                insertLayerGroup( (LayerGroup) mapModelEntry, parent, antecessor, first );
132            }
133        }
134    
135        /**
136         * 
137         * @param layer
138         * @param parent
139         *            if <code>null</code> root node of layertree will be used as parent
140         * @param antecessor
141         *            if <code>null</code> layer will be inserted directly underneath its parent
142         * @param first
143         *            if true layer will be inserted as first layer of a group if antecessor == null
144         */
145        private void insertLayer( MMLayer layer, LayerGroup parent, MapModelEntry antecessor, boolean first ) {
146            insertLayer( layer, parent, antecessor, layerGroups, first );
147        }
148    
149        private void insertLayer( MMLayer layer, LayerGroup parent, MapModelEntry antecessor, List<LayerGroup> lgs,
150                                  boolean first ) {
151            for ( LayerGroup layerGroup : lgs ) {
152                if ( parent != null && parent.equals( layerGroup ) ) {
153                    layerGroup.insert( layer, antecessor, first );
154                    break;
155                } else {
156                    insertLayer( layer, parent, antecessor, layerGroup.getLayerGroups(), first );
157                }
158            }
159        }
160    
161        /**
162         * 
163         * @param layerGroup
164         * @param parent
165         *            if <code>null</code> root node of layer tree will be used as parent
166         * @param antecessor
167         *            if <code>null</code> layer will be inserted directly underneath its parent
168         * @param first
169         *            if true layer will be inserted as first layer group of a group if antecessor == null
170         */
171        private void insertLayerGroup( LayerGroup layerGroup, LayerGroup parent, MapModelEntry antecessor, boolean first ) {
172            if ( parent == null ) {
173                layerGroups.add( layerGroup );
174            }
175            insertLayerGroup( layerGroup, parent, antecessor, layerGroups, first );
176        }
177    
178        private void insertLayerGroup( LayerGroup lg, LayerGroup parent, MapModelEntry antecessor, List<LayerGroup> lgs,
179                                       boolean first ) {
180            for ( LayerGroup layerGroup : lgs ) {
181                if ( parent != null && parent.equals( layerGroup ) ) {
182                    layerGroup.insert( lg, antecessor, first );
183                    break;
184                } else {
185                    insertLayerGroup( lg, parent, antecessor, layerGroup.getLayerGroups(), first );
186                }
187            }
188        }
189    
190        /**
191         * moves the passed layer underneath a new parent and before the passed antecessor.
192         * 
193         * @param mapModelEntry
194         * @param parent
195         *            if <code>null</code> root node of layer tree will be used as parent
196         * @param antecessor
197         *            if <code>null</code> layer will be inserted directly underneath its parent
198         * @param first
199         */
200        public void move( MapModelEntry mapModelEntry, LayerGroup parent, MapModelEntry antecessor, boolean first ) {
201            if ( mapModelEntry instanceof MMLayer ) {
202                move( (MMLayer) mapModelEntry, parent, antecessor, first );
203            } else if ( mapModelEntry instanceof LayerGroup ) {
204                move( (LayerGroup) mapModelEntry, parent, antecessor, first );
205            }
206        }
207    
208        /**
209         * moves the passed layer underneath a new parent and before the passed antecessor.
210         * 
211         * @param layer
212         * @param parent
213         *            if <code>null</code> root node of layertree will be used as parent
214         * @param antecessor
215         *            if <code>null</code> layer will be inserted directly underneath its parent
216         * @param first
217         *            if true layer will be inserted as first layer of a group if antecessor == null
218         */
219        private void move( MMLayer layer, LayerGroup parent, MapModelEntry antecessor, boolean first ) {
220            if ( !layer.equals( antecessor ) ) {
221                layer.getParent().removeLayer( layer );
222                insertLayer( layer, parent, antecessor, layerGroups, first );
223            }
224        }
225    
226        /**
227         * moves the passed layergroup underneath a new parent and before the passed antecessor.
228         * 
229         * @param layerGroup
230         * @param parent
231         *            if <code>null</code> root node of layertree will be used as parent
232         * @param antecessor
233         *            if <code>null</code> layergroup will be inserted directly underneath its parent
234         */
235        private void move( LayerGroup layerGroup, LayerGroup parent, MapModelEntry antecessor, boolean first ) {
236            if ( !layerGroup.equals( antecessor ) ) {
237                layerGroup.getParent().removeLayerGroup( layerGroup );
238                insertLayerGroup( layerGroup, parent, antecessor, layerGroups, first );
239            }
240        }
241    
242        /**
243         * 
244         * @param visitor
245         * @throws Exception
246         */
247        public void walkLayerTree( MapModelVisitor visitor )
248                                throws Exception {
249            for ( LayerGroup layerGroup : layerGroups ) {
250                applyVisitor( layerGroup, visitor );
251            }
252        }
253    
254        private void applyVisitor( LayerGroup layerGroup, MapModelVisitor visitor )
255                                throws Exception {
256            visitor.visit( layerGroup );
257            List<MapModelEntry> entries = layerGroup.getMapModelEntries();
258            for ( MapModelEntry entry : entries ) {
259                if ( entry instanceof MMLayer ) {
260                    visitor.visit( (MMLayer) entry );
261                } else {
262                    applyVisitor( (LayerGroup) entry, visitor );
263                }
264            }
265        }
266    
267        /**
268         * 
269         * @param identifier
270         * @return {@link MapModelEntry} matching passed identifier
271         */
272        public MapModelEntry getMapModelEntryByIdentifier( final String identifier ) {
273            final List<MapModelEntry> list = new ArrayList<MapModelEntry>();
274            try {
275                walkLayerTree( new MapModelVisitor() {
276    
277                    public void visit( LayerGroup layerGroup )
278                                            throws Exception {
279                        if ( identifier.equals( layerGroup.getIdentifier() ) ) {
280                            list.add( layerGroup );
281                        }
282    
283                    }
284    
285                    public void visit( MMLayer layer )
286                                            throws Exception {
287                        if ( identifier.equals( layer.getIdentifier() ) ) {
288                            list.add( layer );
289                        }
290    
291                    }
292                } );
293            } catch ( Exception e ) {
294                e.printStackTrace();
295            }
296            if ( list.size() > 0 ) {
297                return list.get( 0 );
298            } else {
299                return null;
300            }
301        }
302    
303        /**
304         * 
305         * @param mapModelEntry
306         *            {@link MapModelEntry} to remove
307         */
308        public void remove( MapModelEntry mapModelEntry ) {
309            if ( mapModelEntry instanceof MMLayer ) {
310                ( (MMLayer) mapModelEntry ).getParent().removeLayer( (MMLayer) mapModelEntry );
311            } else if ( mapModelEntry instanceof LayerGroup ) {
312                LayerGroup layerGroup = (LayerGroup) mapModelEntry;
313                if ( layerGroup.getParent() != null ) {
314                    layerGroup.getParent().removeLayerGroup( layerGroup );
315                }
316            }
317        }
318    }