001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/context/WebMapContextFactory.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.awt.Rectangle;
039    import java.io.IOException;
040    import java.io.InputStreamReader;
041    import java.io.Reader;
042    import java.net.MalformedURLException;
043    import java.net.URL;
044    import java.util.HashMap;
045    import java.util.Map;
046    
047    import org.apache.commons.httpclient.HttpClient;
048    import org.apache.commons.httpclient.methods.GetMethod;
049    import org.deegree.datatypes.QualifiedName;
050    import org.deegree.enterprise.WebUtils;
051    import org.deegree.framework.log.ILogger;
052    import org.deegree.framework.log.LoggerFactory;
053    import org.deegree.framework.util.Parameter;
054    import org.deegree.framework.util.ParameterList;
055    import org.deegree.framework.util.StringTools;
056    import org.deegree.framework.xml.ElementList;
057    import org.deegree.framework.xml.NamespaceContext;
058    import org.deegree.framework.xml.XMLFragment;
059    import org.deegree.framework.xml.XMLParsingException;
060    import org.deegree.framework.xml.XMLTools;
061    import org.deegree.graphics.sld.FeatureTypeStyle;
062    import org.deegree.graphics.sld.SLDFactory;
063    import org.deegree.graphics.sld.StyledLayerDescriptor;
064    import org.deegree.model.crs.CRSFactory;
065    import org.deegree.model.crs.CoordinateSystem;
066    import org.deegree.model.crs.UnknownCRSException;
067    import org.deegree.model.metadata.iso19115.Address;
068    import org.deegree.model.metadata.iso19115.CitedResponsibleParty;
069    import org.deegree.model.metadata.iso19115.ContactInfo;
070    import org.deegree.model.metadata.iso19115.Phone;
071    import org.deegree.model.metadata.iso19115.RoleCode;
072    import org.deegree.model.spatialschema.GeometryFactory;
073    import org.deegree.model.spatialschema.Point;
074    import org.deegree.ogcbase.BaseURL;
075    import org.deegree.ogcbase.CommonNamespaces;
076    import org.deegree.ogcbase.ImageURL;
077    import org.deegree.ogcwebservices.OWSUtils;
078    import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
079    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
080    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilitiesDocument;
081    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
082    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument;
083    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
084    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
085    import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
086    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
087    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
088    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
089    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
090    import org.deegree.owscommon_new.HTTP;
091    import org.deegree.owscommon_new.Operation;
092    import org.deegree.owscommon_new.OperationsMetadata;
093    import org.deegree.security.drm.model.User;
094    import org.w3c.dom.Element;
095    import org.w3c.dom.Text;
096    import org.xml.sax.SAXException;
097    
098    /**
099     * Factory class for creating an instance of a web map Context (<tt>ViewContext</tt>). The factory is able to parse
100     * deegree specific extensions (General and Layer) as well as standard web map context documents.
101     * 
102     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
103     * @author last edited by: $Author: apoth $
104     * 
105     * @version $Revision: 20709 $, $Date: 2009-11-11 10:28:56 +0100 (Mi, 11. Nov 2009) $
106     */
107    public class WebMapContextFactory {
108    
109        private static final ILogger LOG = LoggerFactory.getLogger( WebMapContextFactory.class );
110    
111        /**
112         * Caching the wms capabilities. Key is the wms address (URL), value is the WMSCapabilities.
113         */
114        private static Map<URL, WMSCapabilities> wmsCache = new HashMap<URL, WMSCapabilities>();
115    
116        private static Map<URL, WFSCapabilities> wfsCache = new HashMap<URL, WFSCapabilities>();
117    
118        private static Map<URL, WCSCapabilities> wcsCache = new HashMap<URL, WCSCapabilities>();
119    
120        /**
121         * creates an instance of a ViewContext from the web map context document read from the passed URL
122         * 
123         * @param url
124         * @param user
125         * @param sessionID
126         * @return new ViewContext for web map context document from <code>url</code>
127         * @throws IOException
128         * @throws XMLParsingException
129         * @throws ContextException
130         * @throws SAXException
131         * @throws UnknownCRSException
132         */
133        public synchronized static ViewContext createViewContext( URL url, User user, String sessionID )
134                                throws IOException, XMLParsingException, ContextException, SAXException,
135                                UnknownCRSException {
136            // cache have to be cleared because contained capabilities may has been
137            // requested with other user identification
138            wmsCache.clear();
139    
140            XMLFragment xml = new XMLFragment( url );
141    
142            return createViewContext( xml, user, sessionID );
143        }
144    
145        /**
146         * @param xml
147         * @param user
148         * @param sessionID
149         * @return new ViewContext for web map context document from <code>xml</code>
150         * @throws IOException
151         * @throws XMLParsingException
152         * @throws ContextException
153         * @throws UnknownCRSException
154         */
155        public synchronized static ViewContext createViewContext( XMLFragment xml, User user, String sessionID )
156                                throws IOException, XMLParsingException, ContextException, UnknownCRSException {
157            // general section
158            Element element = XMLTools.getRequiredChildElement( "General", CommonNamespaces.CNTXTNS, xml.getRootElement() );
159            General general = createGeneral( element, xml );
160    
161            // Layer (List) section
162            element = XMLTools.getRequiredChildElement( "LayerList", CommonNamespaces.CNTXTNS, xml.getRootElement() );
163    
164            final LayerList layerList = createLayerList( element, user, sessionID );
165    
166            GeneralExtension ge = general.getExtension();
167            MapModel mapModel = ge.getMapModel();
168            if ( mapModel != null ) {
169                // WMC layers assigned to MapModel layers just can be set after WMC layer 
170                // list has been parsed
171                try {
172                    mapModel.walkLayerTree( new MapModelVisitor() {
173    
174                        public void visit( LayerGroup layerGroup )
175                                                throws Exception {
176                        }
177    
178                        public void visit( MMLayer layer )
179                                                throws Exception {
180                            Layer[] layers = layerList.getLayers();
181                            for ( Layer layer2 : layers ) {
182                                if ( layer.getIdentifier().equals( layer2.getExtension().getIdentifier() ) ) {
183                                    layer.setLayer( layer2 );
184                                    break;
185                                }
186                            }
187                        }
188                    } );
189                } catch ( Exception e ) {
190                    e.printStackTrace();
191                }
192            }
193    
194            ViewContext vc = new ViewContext( general, layerList );
195    
196            return vc;
197        }
198    
199        /**
200         * creates an instance of a class encapsulating the general context informations
201         * 
202         * @param element
203         *            <General>
204         * @param xml
205         * 
206         * @return instance of <tt>General</tt>
207         * 
208         * @throws XMLParsingException
209         * @throws UnknownCRSException
210         */
211        private static General createGeneral( Element element, XMLFragment xml )
212                                throws XMLParsingException, MalformedURLException, UnknownCRSException {
213    
214            // <Window>
215            Element elem = XMLTools.getChildElement( "Window", CommonNamespaces.CNTXTNS, element );
216            Rectangle rect = createWindow( elem );
217    
218            // <BoundingBox>
219            elem = XMLTools.getRequiredChildElement( "BoundingBox", CommonNamespaces.CNTXTNS, element );
220            Point[] bbox = createBoundingBox( elem );
221    
222            // <Title>
223            String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
224    
225            // <KeywordList>
226            elem = XMLTools.getChildElement( "KeywordList", CommonNamespaces.CNTXTNS, element );
227            String[] keywords = createKeywords( elem );
228    
229            // <Abstract>
230            String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
231    
232            // <LogoURL>
233            elem = XMLTools.getChildElement( "LogoURL", CommonNamespaces.CNTXTNS, element );
234            ImageURL logoURL = createImageURL( elem );
235    
236            // <DescriptionURL>
237    
238            // elem = XMLTools.getChildElement( "DescriptionURL", CommonNamespaces.CNTXTNS, element );
239            elem = XMLTools.getRequiredElement( element, CommonNamespaces.CNTXT_PREFIX + ":DescriptionURL",
240                                                CommonNamespaces.getNamespaceContext() );
241    
242            BaseURL descriptionURL = createBaseURL( elem );
243    
244            // <ContactInformation>
245            elem = XMLTools.getChildElement( "ContactInformation", CommonNamespaces.CNTXTNS, element );
246            CitedResponsibleParty contact = createContactInformation( elem );
247    
248            // <Extension>
249            elem = XMLTools.getChildElement( "Extension", CommonNamespaces.CNTXTNS, element );
250            GeneralExtension extension = createGeneralExtension( elem, xml );
251    
252            General general = null;
253            try {
254                general = new General( title, abstract_, rect, contact, bbox, descriptionURL, logoURL, keywords, extension );
255            } catch ( Exception e ) {
256                throw new XMLParsingException( e.getMessage(), e );
257            }
258    
259            return general;
260        }
261    
262        /**
263         * creates a <tt>Rectangle<tt> (Window) instance from the passed Element.
264         * 
265         * @param element
266         *            <Window>
267         * 
268         * @return instance of <tt>Rectangle</tt>
269         * 
270         * @throws XMLParsingException
271         */
272        private static Rectangle createWindow( Element element )
273                                throws XMLParsingException {
274    
275            Rectangle rect = null;
276    
277            if ( element != null ) {
278                String tmp = XMLTools.getRequiredAttrValue( "width", null, element );
279                int width = Integer.parseInt( tmp );
280                tmp = XMLTools.getRequiredAttrValue( "height", null, element );
281    
282                int height = Integer.parseInt( tmp );
283                rect = new Rectangle( width, height );
284            }
285    
286            return rect;
287        }
288    
289        /**
290         * creates a <tt>Envelope </tt> from the passed Element
291         * 
292         * @param element
293         *            <BoundingBox>
294         * 
295         * @return instance of <tt>Envelope</tt>
296         * 
297         * @throws XMLParsingException
298         * @throws UnknownCRSException
299         */
300        private static Point[] createBoundingBox( Element element )
301                                throws XMLParsingException, UnknownCRSException {
302    
303            String srs = XMLTools.getRequiredAttrValue( "SRS", null, element );
304            CoordinateSystem crs = CRSFactory.create( srs );
305            String tmp = XMLTools.getRequiredAttrValue( "minx", null, element );
306            double minx = Double.parseDouble( tmp );
307            tmp = XMLTools.getRequiredAttrValue( "miny", null, element );
308    
309            double miny = Double.parseDouble( tmp );
310            tmp = XMLTools.getRequiredAttrValue( "maxx", null, element );
311    
312            double maxx = Double.parseDouble( tmp );
313            tmp = XMLTools.getRequiredAttrValue( "maxy", null, element );
314    
315            double maxy = Double.parseDouble( tmp );
316    
317            Point[] points = new Point[2];
318            points[0] = GeometryFactory.createPoint( minx, miny, crs );
319            points[1] = GeometryFactory.createPoint( maxx, maxy, crs );
320    
321            return points;
322        }
323    
324        /**
325         * creates an array of keywords (String) from the passed Keyword list
326         * 
327         * @param element
328         *            <KeywordList>
329         * 
330         * @return array of Strings
331         * 
332         */
333        private static String[] createKeywords( Element element ) {
334    
335            ElementList el = XMLTools.getChildElements( "Keyword", CommonNamespaces.CNTXTNS, element );
336            String[] keywords = new String[el.getLength()];
337    
338            for ( int i = 0; i < keywords.length; i++ ) {
339                keywords[i] = XMLTools.getStringValue( el.item( i ) );
340            }
341    
342            return keywords;
343        }
344    
345        /**
346         * creates an instance of an ImageURL that is used for <LogoURL> and LegendURL
347         * 
348         * @param element
349         *            <LogoURL> or <LegendURL>
350         * 
351         * @return instance of <tt>ImageURL</tt>
352         * 
353         * @throws XMLParsingException
354         */
355        private static ImageURL createImageURL( Element element )
356                                throws XMLParsingException {
357    
358            ImageURL imageURL = null;
359    
360            if ( element != null ) {
361                String tmp = XMLTools.getAttrValue( element, null, "width", null );
362                int width = -1;
363                if ( tmp != null ) {
364                    width = Integer.parseInt( tmp );
365                }
366                tmp = XMLTools.getAttrValue( element, null, "height", null );
367                int height = -1;
368                if ( tmp != null ) {
369                    height = Integer.parseInt( tmp );
370                }
371                String format = XMLTools.getAttrValue( element, null, "format", null );
372    
373                Element elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
374                URL onlineResource = createOnlineResource( elem );
375    
376                imageURL = new ImageURL( width, height, format, onlineResource );
377            }
378    
379            return imageURL;
380        }
381    
382        /**
383         * creates an instance of an URL described by a <OnlineResource> element
384         * 
385         * @param element
386         *            <OnlineResource>
387         * 
388         * @return instance of <tt>URL</tt>
389         * 
390         * @throws XMLParsingException
391         */
392        private static URL createOnlineResource( Element element )
393                                throws XMLParsingException {
394    
395            URL onlineResource = null;
396    
397            if ( element != null ) {
398                // String type = XMLTools.getAttrValue( element, null, "type", null );
399                String type = element.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(), "type" );
400    
401                // if ( type == null || "".equals( type.trim() ) ) {
402                // type = XMLTools.getAttrValue( element, CommonNamespaces.XLNNS, "type", null );
403                // }
404                // System.out.println( "document: " + new XMLFragment( element ).getAsPrettyString() );
405                // System.out.println("Type is: " + type);
406                if ( ( type != null ) && !"".equals( type ) && !type.equals( "simple" ) ) {
407                    throw new XMLParsingException( "unknown type of online resource: " + type );
408                }
409    
410                // String tmp = XMLTools.getAttrValue( element, null, "href", null );
411                String tmp = element.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(), "href" );
412    
413                // if ( tmp == null ) {
414                // tmp = XMLTools.getAttrValue( element, CommonNamespaces.XLNNS, "href", null );
415                // }
416    
417                // System.out.println("href is: " + tmp);
418                try {
419                    onlineResource = new URL( tmp );
420                } catch ( Exception e ) {
421                    throw new XMLParsingException( "couldn't create online resource", e );
422                }
423            }
424    
425            return onlineResource;
426        }
427    
428        /**
429         * creates an instance of BaseURL that is used for <DescriptionURL>
430         * 
431         * @param element
432         *            <DescriptionURL>
433         * @return instance of <tt>BaseURL</tt>, or null, if the passed element is null
434         * @throws XMLParsingException
435         */
436        private static BaseURL createBaseURL( Element element )
437                                throws XMLParsingException {
438    
439            BaseURL baseURL = null;
440    
441            if ( element != null ) {
442                String format = XMLTools.getAttrValue( element, null, "format", null );
443    
444                Element elem = XMLTools.getElement( element, CommonNamespaces.CNTXT_PREFIX + ":OnlineResource",
445                                                    CommonNamespaces.getNamespaceContext() );
446                URL onlineResource = createOnlineResource( elem );
447    
448                baseURL = new BaseURL( format, onlineResource );
449            }
450    
451            return baseURL;
452        }
453    
454        /**
455         * Creates a <tt>ContactInformation</tt>-instance according to the contents of the DOM-subtree starting at the given
456         * 'ContactInformation'-<tt>Element</tt>.
457         * <p>
458         * 
459         * @param element
460         *            the 'ContactInformation'-<tt>Element</tt>
461         * @throws XMLParsingException
462         *             if a syntactic or semantic error in the DOM-subtree is encountered
463         * @return the constructed <tt>ContactInformation</tt>-instance
464         */
465        private static CitedResponsibleParty createContactInformation( Element element )
466                                throws XMLParsingException {
467    
468            CitedResponsibleParty contact = null;
469    
470            if ( element != null ) {
471                // optional: <ContactPersonPrimary>
472                Element contactPersonPrimaryElement = XMLTools.getChildElement( "ContactPersonPrimary",
473                                                                                CommonNamespaces.CNTXTNS, element );
474    
475                String contactPerson = null;
476                String contactOrganization = null;
477                if ( contactPersonPrimaryElement != null ) {
478                    // required: <ContactPerson>
479                    contactPerson = XMLTools.getRequiredStringValue( "ContactPerson", CommonNamespaces.CNTXTNS,
480                                                                     contactPersonPrimaryElement );
481    
482                    // required: <ContactOrganization>
483                    contactOrganization = XMLTools.getRequiredStringValue( "ContactOrganization", CommonNamespaces.CNTXTNS,
484                                                                           contactPersonPrimaryElement );
485                }
486    
487                // optional: <ContactPosition>
488                String contactPosition = XMLTools.getStringValue( "ContactPosition", CommonNamespaces.CNTXTNS, element,
489                                                                  null );
490    
491                // optional: <ContactAddress>
492                Address contactAddress = null;
493                Element contactAddressElement = XMLTools.getChildElement( "ContactAddress", CommonNamespaces.CNTXTNS,
494                                                                          element );
495    
496                if ( contactAddressElement != null ) {
497                    // optional: <ContactElectronicMailAddress>
498                    String eMailAddress = XMLTools.getStringValue( "ContactElectronicMailAddress",
499                                                                   CommonNamespaces.CNTXTNS, element, null );
500                    contactAddress = createContactAddress( eMailAddress, contactAddressElement );
501                }
502    
503                // optional: <ContactVoiceTelephone>
504                String voice = XMLTools.getStringValue( "ContactVoiceTelephone", CommonNamespaces.CNTXTNS, element, null );
505    
506                // optional: <ContactFacsimileTelephone>
507                String fax = XMLTools.getStringValue( "ContactFacsimileTelephone", CommonNamespaces.CNTXTNS, element, null );
508    
509                Phone phone = new Phone( new String[] { fax }, new String[] { voice } );
510                ContactInfo ci = new ContactInfo( contactAddress, null, null, null, phone );
511                contact = new CitedResponsibleParty( new ContactInfo[] { ci }, new String[] { contactPerson },
512                                                     new String[] { contactOrganization },
513                                                     new String[] { contactPosition }, new RoleCode[0] );
514            }
515    
516            return contact;
517        }
518    
519        /**
520         * Creates a <tt>ContactAddress</tt>-instance according to the contents of the DOM-subtree starting at the given
521         * 'ContactAddress'-<tt>Element</tt>.
522         * <p>
523         * 
524         * @param element
525         *            the 'ContactAddress'-<tt>Element</tt>
526         * @throws XMLParsingException
527         *             if a syntactic or semantic error in the DOM-subtree is encountered
528         * @return the constructed <tt>ContactAddress</tt>-instance
529         */
530        private static Address createContactAddress( String eMail, Element element )
531                                throws XMLParsingException {
532    
533            // required: <AddressType>
534            /*
535             * String addressType = XMLTools.getRequiredStringValue( "AddressType", CommonNamespaces.CNTXTNS, element );
536             */
537            // required: <Address>
538            String address = XMLTools.getRequiredStringValue( "Address", CommonNamespaces.CNTXTNS, element );
539    
540            // required: <City>
541            String city = XMLTools.getRequiredStringValue( "City", CommonNamespaces.CNTXTNS, element );
542    
543            // required: <StateOrProvince>
544            String stateOrProvince = XMLTools.getRequiredStringValue( "StateOrProvince", CommonNamespaces.CNTXTNS, element );
545    
546            // required: <PostCode>
547            String postCode = XMLTools.getRequiredStringValue( "PostCode", CommonNamespaces.CNTXTNS, element );
548    
549            // required: <Country>
550            String country = XMLTools.getRequiredStringValue( "Country", CommonNamespaces.CNTXTNS, element );
551    
552            return new Address( stateOrProvince, city, country, new String[] { address }, new String[] { eMail }, postCode );
553        }
554    
555        /**
556         * creates an instance of a class encapsulating the deegree specific extensions of the general section of a web map
557         * context document
558         * 
559         * @param element
560         *            <Extension>
561         * @param xml
562         * 
563         * @return instance of <tt>GeneralExtension</tt>
564         * 
565         * @throws XMLParsingException
566         */
567        private static GeneralExtension createGeneralExtension( Element element, XMLFragment xml )
568                                throws XMLParsingException, MalformedURLException {
569    
570            GeneralExtension ge = null;
571    
572            if ( element != null ) {
573    
574                // retunrs the current mode of a client using a WMC
575                String mode = XMLTools.getStringValue( "Mode", CommonNamespaces.DGCNTXTNS, element, "ZOOMIN" );
576    
577                // <AuthentificationSettings>
578                Element elem = XMLTools.getChildElement( "AuthentificationSettings", CommonNamespaces.DGCNTXTNS, element );
579                AuthentificationSettings authSettings = null;
580                if ( elem != null ) {
581                    authSettings = createAuthentificationSettings( elem );
582                }
583                // <IOSetiings>
584                elem = XMLTools.getChildElement( "IOSettings", CommonNamespaces.DGCNTXTNS, element );
585                IOSettings ioSettings = null;
586                if ( elem != null ) {
587                    ioSettings = createIOSettings( elem, xml );
588                }
589                // <Frontend>
590                elem = XMLTools.getChildElement( "Frontend", CommonNamespaces.DGCNTXTNS, element );
591                Frontend frontend = null;
592                if ( elem != null ) {
593                    frontend = createFrontend( elem );
594                }
595                // <MapParameter>
596                elem = XMLTools.getRequiredChildElement( "MapParameter", CommonNamespaces.DGCNTXTNS, element );
597                MapParameter mapParameter = createMapParameter( elem );
598    
599                // <LayerTree> old version
600                elem = XMLTools.getChildElement( "LayerTree", CommonNamespaces.DGCNTXTNS, element );
601    
602                Node layerTreeRoot = null;
603                if ( elem != null ) {
604                    Element nodeElem = XMLTools.getRequiredChildElement( "Node", CommonNamespaces.DGCNTXTNS, elem );
605                    layerTreeRoot = createNode( nodeElem, null );
606                } else {
607                    try {
608                        layerTreeRoot = new Node( 0, null, "root", false, false );
609                        Node[] nodes = new Node[] { new Node( 1, layerTreeRoot, "deegree", false, false ) };
610                        layerTreeRoot.setNodes( nodes );
611                    } catch ( ContextException e ) {
612                        throw new XMLParsingException( "couldn't create layertree node", e );
613                    }
614                }
615    
616                elem = XMLTools.getChildElement( "MapModel", CommonNamespaces.DGCNTXTNS, element );
617                MapModel mapModel = null;
618                if ( elem != null ) {
619                    MapModelDocument doc = new MapModelDocument( elem );
620                    mapModel = doc.parseMapModel();
621                }
622    
623                ge = new GeneralExtension( ioSettings, frontend, mapParameter, authSettings, mode, layerTreeRoot, mapModel );
624            }
625    
626            return ge;
627        }
628    
629        /**
630         * creates a node in the layerTree
631         */
632        private static Node createNode( Element nodeElem, Node parent )
633                                throws XMLParsingException {
634    
635            int id = Integer.parseInt( XMLTools.getRequiredAttrValue( "id", null, nodeElem ) );
636            String title = XMLTools.getRequiredAttrValue( "title", null, nodeElem );
637            String s = XMLTools.getAttrValue( nodeElem, null, "selectable", null );
638            boolean selectable = "true".equals( s ) || "1".equals( s );
639            s = XMLTools.getAttrValue( nodeElem, null, "collapsed", null );
640            boolean collapsed = "true".equals( s ) || "1".equals( s );
641            Node node = null;
642            try {
643                node = new Node( id, parent, title, selectable, collapsed );
644            } catch ( Exception e ) {
645                throw new XMLParsingException( "couldn't create layertree node", e );
646            }
647    
648            // get Child nodes
649            ElementList nl = XMLTools.getChildElements( "Node", CommonNamespaces.DGCNTXTNS, nodeElem );
650            Node[] nodes = new Node[nl.getLength()];
651            for ( int i = 0; i < nodes.length; i++ ) {
652                nodes[i] = createNode( nl.item( i ), node );
653            }
654            // set child nodes
655            node.setNodes( nodes );
656    
657            return node;
658        }
659    
660        /**
661         * creates an instance of a class encapsulating access descrition to an authentification service for a deegree map
662         * client
663         * 
664         * @param element
665         *            <AuthentificationSettings>
666         * @return instance of <tt>AuthentificationSettings</tt>
667         * @throws XMLParsingException
668         */
669        private static AuthentificationSettings createAuthentificationSettings( Element element )
670                                throws XMLParsingException {
671    
672            Element elem = XMLTools.getRequiredChildElement( "AuthentificationService", CommonNamespaces.DGCNTXTNS, element );
673            elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, elem );
674    
675            URL url = createOnlineResource( elem );
676            BaseURL bu = new BaseURL( "text/xml", url );
677    
678            return new AuthentificationSettings( bu );
679        }
680    
681        /**
682         * creates an instance of a class encapsulating the frontend (GUI) description of a deegree map client
683         * 
684         * @param element
685         *            <Frontend>
686         * 
687         * @return instance of <tt>Frontend</tt>
688         * 
689         * @throws XMLParsingException
690         */
691        private static Frontend createFrontend( Element element )
692                                throws XMLParsingException {
693    
694            // <Controller>
695            String controller = XMLTools.getRequiredStringValue( "Controller", CommonNamespaces.DGCNTXTNS, element );
696            // <Style>
697            String style = XMLTools.getStringValue( "Style", CommonNamespaces.DGCNTXTNS, element, null );
698            // <Buttons>
699            String buttons = XMLTools.getStringValue( "Buttons", CommonNamespaces.DGCNTXTNS, element, null );
700            // <CommonJS>
701            Element elem = XMLTools.getChildElement( "CommonJS", CommonNamespaces.DGCNTXTNS, element );
702            String[] commonJS = createCommonJS( elem );
703            // <West>
704            elem = XMLTools.getChildElement( "West", CommonNamespaces.DGCNTXTNS, element );
705            GUIArea west = createGUIArea( elem );
706            // <East>
707            elem = XMLTools.getChildElement( "East", CommonNamespaces.DGCNTXTNS, element );
708            GUIArea east = createGUIArea( elem );
709            // <North>
710            elem = XMLTools.getChildElement( "North", CommonNamespaces.DGCNTXTNS, element );
711            GUIArea north = createGUIArea( elem );
712            // <South>
713            elem = XMLTools.getChildElement( "South", CommonNamespaces.DGCNTXTNS, element );
714            GUIArea south = createGUIArea( elem );
715            // <Center>
716            elem = XMLTools.getChildElement( "Center", CommonNamespaces.DGCNTXTNS, element );
717            GUIArea center = createGUIArea( elem );
718            // <Header>
719            String header = XMLTools.getStringValue( "Header", CommonNamespaces.DGCNTXTNS, element, null );
720            // <Footer>
721            String footer = XMLTools.getStringValue( "Footer", CommonNamespaces.DGCNTXTNS, element, null );
722    
723            Frontend frontend = new JSPFrontend( controller, west, east, south, north, center, style, buttons, commonJS,
724                                                 header, footer );
725    
726            return frontend;
727        }
728    
729        /**
730         * creates a list of javascript pages (names) that contains javascript objects and methods that are used by more
731         * than one module
732         * 
733         * @param element
734         *            <CommonJS>
735         * 
736         * @return instance of <tt>String[]</tt>
737         * 
738         */
739        private static String[] createCommonJS( Element element ) {
740            String[] commonJS = null;
741            if ( element != null ) {
742                ElementList el = XMLTools.getChildElements( "Name", CommonNamespaces.DGCNTXTNS, element );
743                commonJS = new String[el.getLength()];
744                for ( int i = 0; i < commonJS.length; i++ ) {
745                    commonJS[i] = XMLTools.getStringValue( el.item( i ) );
746                }
747            }
748    
749            return commonJS;
750        }
751    
752        /**
753         * creates an instance of a class encapsulating the GUI description of one region of the GUI
754         * 
755         * @param element
756         *            <West>; <East>; <South>; <North> or <Center>
757         * 
758         * @return instance of <tt>GUIArea</tt>
759         * 
760         * @throws XMLParsingException
761         */
762        private static GUIArea createGUIArea( Element element )
763                                throws XMLParsingException {
764    
765            GUIArea gui = null;
766            if ( element != null ) {
767                String tmp = element.getLocalName();
768                int area = 0;
769                if ( tmp.equals( "West" ) ) {
770                    area = GUIArea.WEST;
771                } else if ( tmp.equals( "East" ) ) {
772                    area = GUIArea.EAST;
773                } else if ( tmp.equals( "South" ) ) {
774                    area = GUIArea.SOUTH;
775                } else if ( tmp.equals( "North" ) ) {
776                    area = GUIArea.NORTH;
777                } else if ( tmp.equals( "Center" ) ) {
778                    area = GUIArea.CENTER;
779                }
780    
781                NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
782                int w = XMLTools.getNodeAsInt( element, "./@width", nsContext, -1 );
783                int h = XMLTools.getNodeAsInt( element, "./@height", nsContext, -1 );
784                int l = XMLTools.getNodeAsInt( element, "./@left", nsContext, -1 );
785                int t = XMLTools.getNodeAsInt( element, "./@top", nsContext, -1 );
786                int r = XMLTools.getNodeAsInt( element, "./@right", nsContext, -1 );
787                int b = XMLTools.getNodeAsInt( element, "./@bottom", nsContext, -1 );
788                boolean ov = XMLTools.getNodeAsBoolean( element, "./@overlay", nsContext, false );
789                boolean head = XMLTools.getNodeAsBoolean( element, "./@header", nsContext, false );
790                boolean close = XMLTools.getNodeAsBoolean( element, "./@closable", nsContext, false );
791    
792                // hidden
793                tmp = XMLTools.getAttrValue( element, null, "hidden", null );
794                boolean hidden = "1".equals( tmp ) || "true".equals( tmp );
795                // <Module>
796                ElementList el = XMLTools.getChildElements( "Module", CommonNamespaces.DGCNTXTNS, element );
797                Module[] modules = new Module[el.getLength()];
798                for ( int i = 0; i < modules.length; i++ ) {
799                    modules[i] = createModule( el.item( i ) );
800                }
801                gui = new GUIArea( area, hidden, w, h, l, t, r, b, ov, head, close, modules );
802            }
803    
804            return gui;
805        }
806    
807        /**
808         * creates an instance of a class encapsulating module informations
809         * 
810         * @param element
811         *            <Module>
812         * 
813         * @return instance of <tt>Module</tt>
814         * 
815         * @throws XMLParsingException
816         */
817        private static Module createModule( Element element )
818                                throws XMLParsingException {
819    
820            // hidden
821            String tmp = XMLTools.getAttrValue( element, null, "hidden", null );
822            boolean hidden = tmp.equals( "1" ) || tmp.equals( "true" );
823            // <Name>
824            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.DGCNTXTNS, element );
825            // <Content>
826            String content = XMLTools.getRequiredStringValue( "Content", CommonNamespaces.DGCNTXTNS, element );
827            // <ModuleConfiguration>
828            Element elem = XMLTools.getChildElement( "ModuleConfiguration", CommonNamespaces.DGCNTXTNS, element );
829            ModuleConfiguration mc = createModuleConfiguration( elem );
830            // <ParameterList>
831            elem = XMLTools.getChildElement( "ParameterList", CommonNamespaces.DGCNTXTNS, element );
832            ParameterList paramList = createParameterList( elem );
833    
834            String type = XMLTools.getAttrValue( element, null, "type", null );
835    
836            // width and height of a Module are optional
837            // if not set '0' will be used instead
838            NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
839            int w = XMLTools.getNodeAsInt( element, "./@width", nsContext, -1 );
840            int h = XMLTools.getNodeAsInt( element, "./@height", nsContext, -1 );
841            int l = XMLTools.getNodeAsInt( element, "./@left", nsContext, -1 );
842            int t = XMLTools.getNodeAsInt( element, "./@top", nsContext, -1 );
843            int b = XMLTools.getNodeAsInt( element, "./@bottom", nsContext, -1 );
844            int r = XMLTools.getNodeAsInt( element, "./@right", nsContext, -1 );
845            boolean ov = XMLTools.getNodeAsBoolean( element, "./@overlay", nsContext, false );
846            boolean head = XMLTools.getNodeAsBoolean( element, "./@header", nsContext, false );
847            boolean close = XMLTools.getNodeAsBoolean( element, "./@closable", nsContext, false );
848    
849            String scrollable = XMLTools.getAttrValue( element, null, "scrolling", null );
850    
851            String[] moduleJS = createModuleJSList( element );
852            return new Module( name, content, hidden, type, l, t, r, b, w, h, ov, head, close, scrollable, moduleJS, mc,
853                               paramList );
854        }
855    
856        /**
857         * creates an instance of a class encapsulating the access the configuration of Module
858         * 
859         * @param element
860         *            <ModuleConfiguration>
861         * 
862         * @return instance of <tt>ModuleConfiguration</tt>
863         * 
864         * @throws XMLParsingException
865         */
866        private static ModuleConfiguration createModuleConfiguration( Element element )
867                                throws XMLParsingException {
868    
869            ModuleConfiguration mc = null;
870            if ( element != null ) {
871                Element elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.DGCNTXTNS, element );
872                URL onlineResource = createOnlineResource( elem );
873                mc = new ModuleConfiguration( onlineResource );
874            }
875    
876            return mc;
877        }
878    
879        /**
880         * creates an instance of a class encapsulating the layer list informations
881         * 
882         * @param element
883         *            <LayerList>
884         * 
885         * @return instance of <tt>LayerList</tt>
886         * 
887         * @throws XMLParsingException
888         */
889        private static ParameterList createParameterList( Element element )
890                                throws XMLParsingException {
891    
892            ParameterList parameterList = new ParameterList();
893            if ( element != null ) {
894                ElementList el = XMLTools.getChildElements( "Parameter", CommonNamespaces.DGCNTXTNS, element );
895                for ( int i = 0; i < el.getLength(); i++ ) {
896                    Parameter parameter = createParameter( el.item( i ) );
897                    parameterList.addParameter( parameter );
898                }
899            }
900    
901            return parameterList;
902        }
903    
904        /**
905         * creates an instance of a class encapsulating a parameter that shall be passed to a module
906         * 
907         * @param element
908         *            <Parameter>
909         * 
910         * @return instance of <tt>Parameter</tt>
911         * 
912         * @throws XMLParsingException
913         */
914        private static Parameter createParameter( Element element )
915                                throws XMLParsingException {
916    
917            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.DGCNTXTNS, element );
918            String value = XMLTools.getRequiredStringValue( "Value", CommonNamespaces.DGCNTXTNS, element );
919            // Parameter param = new Parameter_Impl( name+":"+value, value );
920            Parameter param = new Parameter( name, value );
921    
922            return param;
923        }
924    
925        /**
926         * creates an instance of a class encapsulating informations about controlling options for a map presented to the
927         * user
928         * 
929         * @param element
930         *            <MapParameter>
931         * 
932         * @return instance of <tt>MapParameter</tt>
933         * 
934         * @throws XMLParsingException
935         */
936        private static MapParameter createMapParameter( Element element )
937                                throws XMLParsingException {
938    
939            // <OfferedInfoFormats>
940            Element elem = XMLTools.getChildElement( "OfferedInfoFormats", CommonNamespaces.DGCNTXTNS, element );
941            Format[] infoFormats = null;
942            if ( elem != null ) {
943                infoFormats = createOfferedInfoFormats( elem );
944            }
945            // <OfferedZoomFactor>
946            elem = XMLTools.getChildElement( "OfferedZoomFactor", CommonNamespaces.DGCNTXTNS, element );
947            MapOperationFactor[] zoomFactors = null;
948            if ( elem != null ) {
949                zoomFactors = createOfferedMapOperationFactors( elem );
950            }
951            // <OfferedPanFactor>
952            elem = XMLTools.getChildElement( "OfferedPanFactor", CommonNamespaces.DGCNTXTNS, element );
953            MapOperationFactor[] panFactors = null;
954            if ( elem != null ) {
955                panFactors = createOfferedMapOperationFactors( elem );
956            }
957            // <MinScale>
958            String tmp = XMLTools.getStringValue( "MinScale", CommonNamespaces.DGCNTXTNS, element, "0" );
959            double minScale = Double.parseDouble( tmp );
960            // <MaxScale>
961            tmp = XMLTools.getStringValue( "MaxScale", CommonNamespaces.DGCNTXTNS, element, "9999999999" );
962            double maxScale = Double.parseDouble( tmp );
963    
964            MapParameter mp = new MapParameter( infoFormats, panFactors, zoomFactors, minScale, maxScale );
965    
966            return mp;
967        }
968    
969        /**
970         * Creates a list of the feature info formats offered by the client.
971         * 
972         * @param element
973         *            <OfferedInfoFormats> element of the configuration
974         * 
975         * @return list of offered feature info formats
976         * 
977         * @throws XMLParsingException
978         */
979        private static Format[] createOfferedInfoFormats( Element element )
980                                throws XMLParsingException {
981    
982            Format[] format = null;
983    
984            // get list of offered feature info formats
985            ElementList el = XMLTools.getChildElements( "Format", CommonNamespaces.DGCNTXTNS, element );
986    
987            format = new Format[el.getLength()];
988    
989            for ( int i = 0; i < el.getLength(); i++ ) {
990                String name = XMLTools.getStringValue( el.item( i ) );
991                String sel = XMLTools.getAttrValue( el.item( i ), null, "selected", null );
992    
993                boolean selected = "1".equals( sel ) || "true".equals( sel );
994                try {
995                    format[i] = new Format( name, selected );
996                } catch ( ContextException e ) {
997                    throw new XMLParsingException( "", e );
998                }
999            }
1000    
1001            return format;
1002        }
1003    
1004        /**
1005         * returns a list of offered numerical map operation factors that can be used to determine zoom or pan levels
1006         * 
1007         * @param element
1008         *            a <tt>Element</tt> that contains <Factor> elements as children
1009         * 
1010         * @return list of <tt>MapOperationFactor</tt>s
1011         * 
1012         */
1013        private static MapOperationFactor[] createOfferedMapOperationFactors( Element element ) {
1014    
1015            // get list of offered factors
1016            ElementList el = XMLTools.getChildElements( "Factor", CommonNamespaces.DGCNTXTNS, element );
1017    
1018            MapOperationFactor[] mof = new MapOperationFactor[el.getLength()];
1019    
1020            for ( int i = 0; i < el.getLength(); i++ ) {
1021                boolean free = true;
1022                String tmp = XMLTools.getStringValue( el.item( i ) );
1023                double fac = -99;
1024    
1025                if ( !tmp.equals( "*" ) ) {
1026                    free = false;
1027                    fac = Double.parseDouble( tmp );
1028                }
1029    
1030                String sel = XMLTools.getAttrValue( el.item( i ), null, "selected", null );
1031                boolean selected = "1".equals( sel ) || "true".equals( sel );
1032                mof[i] = new MapOperationFactor( fac, selected, free );
1033            }
1034    
1035            return mof;
1036        }
1037    
1038        /**
1039         * creates an instance of a class encapsulating the IO setting informations
1040         * 
1041         * @param element
1042         * @param xml
1043         * @return the iosettings.
1044         * @throws XMLParsingException
1045         */
1046        private static IOSettings createIOSettings( Element element, XMLFragment xml )
1047                                throws XMLParsingException, MalformedURLException {
1048    
1049            // temp directory
1050            Element elem = XMLTools.getChildElement( "TempDirectory", CommonNamespaces.DGCNTXTNS, element );
1051            DirectoryAccess temp = null;
1052            if ( elem != null ) {
1053                temp = createDirectoryAccess( elem, null, xml );
1054            }
1055            // download directory
1056            elem = XMLTools.getChildElement( "DownloadDirectory", CommonNamespaces.DGCNTXTNS, element );
1057            DirectoryAccess download = null;
1058            if ( elem != null ) {
1059                download = createDirectoryAccess( elem, temp, xml );
1060            }
1061            if ( temp == null && elem == null ) {
1062                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "downloaddirectory must be set!" );
1063            }
1064            // SLD directory
1065            elem = XMLTools.getChildElement( "SLDDirectory", CommonNamespaces.DGCNTXTNS, element );
1066            DirectoryAccess sld = null;
1067            if ( elem != null ) {
1068                sld = createDirectoryAccess( elem, temp, xml );
1069            }
1070            if ( temp == null && elem == null ) {
1071                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "slddirectory must be set!" );
1072            }
1073            // Print directory
1074            elem = XMLTools.getChildElement( "PrintDirectory", CommonNamespaces.DGCNTXTNS, element );
1075            DirectoryAccess print = null;
1076            if ( elem != null ) {
1077                print = createDirectoryAccess( elem, temp, xml );
1078            }
1079            if ( temp == null && elem == null ) {
1080                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "printdirectory must be set!" );
1081            }
1082    
1083            IOSettings ioSettings = new IOSettings( download, sld, print, temp );
1084    
1085            return ioSettings;
1086        }
1087    
1088        /**
1089         * @param element
1090         * @param tempDir
1091         * @return the directory access.
1092         * @throws XMLParsingException
1093         */
1094        private static DirectoryAccess createDirectoryAccess( Element element, DirectoryAccess tempDir, XMLFragment xml )
1095                                throws XMLParsingException, MalformedURLException {
1096    
1097            // directory name
1098            String name = XMLTools.getStringValue( "Name", CommonNamespaces.DGCNTXTNS, element, null );
1099            name = xml.resolve( name ).toExternalForm();
1100    
1101            URL url = null;
1102            Element elem = XMLTools.getChildElement( "Access", CommonNamespaces.DGCNTXTNS, element );
1103            if ( elem != null ) {
1104                elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, elem );
1105                url = createOnlineResource( elem );
1106            }
1107    
1108            DirectoryAccess da = null;
1109            if ( name == null || url == null ) {
1110                da = tempDir;
1111            } else {
1112                da = new DirectoryAccess( xml.resolve( name ).toExternalForm(), url );
1113            }
1114    
1115            return da;
1116    
1117        }
1118    
1119        /**
1120         * creates an instance of a class encapsulating the layer list informations
1121         * 
1122         * @param element
1123         *            <LayerList>
1124         * @param user
1125         * @param sessionID
1126         * 
1127         * @return instance of <tt>LayerList</tt>
1128         * 
1129         * @throws XMLParsingException
1130         */
1131        private static LayerList createLayerList( Element element, User user, String sessionID )
1132                                throws XMLParsingException {
1133    
1134            ElementList el = XMLTools.getChildElements( "Layer", CommonNamespaces.CNTXTNS, element );
1135            Layer[] layers = new Layer[el.getLength()];
1136            for ( int i = 0; i < layers.length; i++ ) {
1137                layers[i] = createLayer( el.item( i ), user, sessionID );
1138            }
1139            LayerList list = new LayerList( layers );
1140    
1141            return list;
1142        }
1143    
1144        /**
1145         * creates an instance of a class encapsulating a web map context layer's attributes
1146         * 
1147         * @param element
1148         *            <Layer>
1149         * @param user
1150         * @param sessionID
1151         * 
1152         * @return instance of <tt>Layer</tt>
1153         * 
1154         * @throws XMLParsingException
1155         */
1156        private static Layer createLayer( Element element, User user, String sessionID )
1157                                throws XMLParsingException {
1158    
1159            String tmp = XMLTools.getRequiredAttrValue( "queryable", null, element );
1160            boolean queryable = "1".equals( tmp ) || "true".equals( tmp );
1161            tmp = XMLTools.getRequiredAttrValue( "hidden", null, element );
1162            boolean hidden = "1".equals( tmp ) || "true".equals( tmp );
1163    
1164            // <Name>
1165            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1166            // <Title>
1167            String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
1168            // <Abstract>
1169            String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
1170            // <DataURL>
1171            Element elem = XMLTools.getChildElement( "DataURL", CommonNamespaces.CNTXTNS, element );
1172            BaseURL dataURL = createBaseURL( elem );
1173            // <MetaDataURL>
1174            elem = XMLTools.getChildElement( "MetadataURL", CommonNamespaces.CNTXTNS, element );
1175            BaseURL metadataURL = createBaseURL( elem );
1176            // <SRS>
1177            tmp = XMLTools.getStringValue( "SRS", CommonNamespaces.CNTXTNS, element, null );
1178            String[] srs = StringTools.toArray( tmp, ",; ", true );
1179            // <FormatList>
1180            elem = XMLTools.getChildElement( "FormatList", CommonNamespaces.CNTXTNS, element );
1181            FormatList formatList = createFormatList( elem );
1182            // <Extension>
1183            Element extElem = XMLTools.getChildElement( "Extension", CommonNamespaces.CNTXTNS, element );
1184            LayerExtension extension = createLayerExtension( extElem, user, sessionID );
1185            // <Server>
1186            elem = XMLTools.getRequiredChildElement( "Server", CommonNamespaces.CNTXTNS, element );
1187            Server server = createServer( elem, user, sessionID, extension.getAuthentication() );
1188    
1189            // try setting metadataURl again. this time from server.
1190            if ( metadataURL == null ) {
1191                metadataURL = createMetadataURL( name, server );
1192            }
1193    
1194            // TODO
1195            // must be removed, if reading capabilities from remote WMS is too slow
1196            setScaleHint( extElem, name, extension, server, user, sessionID, extension.getAuthentication() );
1197    
1198            // <StyleList>
1199            elem = XMLTools.getChildElement( "StyleList", CommonNamespaces.CNTXTNS, element );
1200            StyleList styleList = createStyleList( elem, name, server );
1201    
1202            Layer layer = null;
1203            try {
1204                layer = new Layer( server, name, title, abstract_, srs, dataURL, metadataURL, formatList, styleList,
1205                                   queryable, hidden, extension );
1206            } catch ( Exception e ) {
1207                throw new XMLParsingException( "couldn't create map context layer", e );
1208            }
1209    
1210            return layer;
1211        }
1212    
1213        /**
1214         * @param layerName
1215         *            the layer name from which to take the MetadataURL information
1216         * @param server
1217         *            the WMS server from which to read the layer information (WMS capabilities document)
1218         * @return only the first MetadataURL from the WMS capabilities for the given layer
1219         * @throws XMLParsingException
1220         */
1221        private static BaseURL createMetadataURL( String layerName, Server server )
1222                                throws XMLParsingException {
1223    
1224            WMSCapabilities capa = (WMSCapabilities) server.getCapabilities();
1225            BaseURL metaURL = null;
1226    
1227            if ( capa != null ) {
1228                org.deegree.ogcwebservices.wms.capabilities.Layer layer = capa.getLayer( layerName );
1229                if ( layer != null ) {
1230                    MetadataURL[] urls = layer.getMetadataURL();
1231                    if ( urls != null && urls.length > 0 ) {
1232                        metaURL = urls[0];
1233                    }
1234                } else {
1235                    if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
1236                        String msg = StringTools.concat( 500, "LayerName '", layerName,
1237                                                         "' does not exist in the WMSCapabilities of server ",
1238                                                         server.getOnlineResource() );
1239                        LOG.logDebug( msg );
1240                    }
1241                }
1242            }
1243            return metaURL;
1244        }
1245    
1246        /**
1247         * creates an instance of a class encapsulating informations about the server (service) a layer based on
1248         * 
1249         * @param element
1250         *            <Server>
1251         * @param user
1252         * @param sessionID
1253         * @param useAuthentication
1254         * 
1255         * @return instance of <tt>Server</tt>
1256         * 
1257         * @throws XMLParsingException
1258         */
1259        private static Server createServer( Element element, User user, String sessionID, int useAuthentication )
1260                                throws XMLParsingException {
1261    
1262            String service = XMLTools.getRequiredAttrValue( "service", null, element );
1263            String version = XMLTools.getRequiredAttrValue( "version", null, element );
1264            String title = XMLTools.getRequiredAttrValue( "title", null, element );
1265            // <OnlineResource>
1266            Element elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
1267            URL onlineResource = createOnlineResource( elem );
1268    
1269            OGCCapabilities capabilities = getCapabilities( onlineResource, service, version, user, sessionID,
1270                                                            useAuthentication );
1271    
1272            Server server = null;
1273            try {
1274                server = new Server( title, version, service, onlineResource, capabilities );
1275            } catch ( Exception e ) {
1276                LOG.logError( e.getMessage(), e );
1277                throw new XMLParsingException( "could not create context server", e );
1278            }
1279    
1280            return server;
1281        }
1282    
1283        /**
1284         * creates an instance of a class encapsulating a list of image formats a layer offers
1285         * 
1286         * @param element
1287         *            <FormatList>
1288         * 
1289         * @return instance of <tt>FormatList</tt>
1290         * 
1291         * @throws XMLParsingException
1292         */
1293        private static FormatList createFormatList( Element element )
1294                                throws XMLParsingException {
1295    
1296            ElementList el = XMLTools.getChildElements( "Format", CommonNamespaces.CNTXTNS, element );
1297            Format[] formats = new Format[el.getLength()];
1298            for ( int i = 0; i < formats.length; i++ ) {
1299                String name = XMLTools.getStringValue( el.item( i ) );
1300                String tmp = XMLTools.getAttrValue( el.item( i ), null, "current", null );
1301                boolean current = "1".equals( tmp ) || "true".equals( tmp ) || formats.length == 1;
1302                try {
1303                    formats[i] = new Format( name, current );
1304                } catch ( Exception e ) {
1305                    throw new XMLParsingException( "could not create context format", e );
1306                }
1307            }
1308    
1309            FormatList formatList = null;
1310            try {
1311                formatList = new FormatList( formats );
1312            } catch ( Exception e ) {
1313                LOG.logDebug( e.getMessage(), e );
1314                throw new XMLParsingException( "could not create context formatList", e );
1315            }
1316    
1317            return formatList;
1318        }
1319    
1320        /**
1321         * creates an instance of a class encapsulating a list of styles available for a layer
1322         * 
1323         * @param element
1324         *            <StyleList>
1325         * @param layerName
1326         * @param server
1327         * 
1328         * @return instance of <tt>StyleList</tt>
1329         * 
1330         * @throws XMLParsingException
1331         */
1332        private static StyleList createStyleList( Element element, String layerName, Server server )
1333                                throws XMLParsingException {
1334    
1335            ElementList el = XMLTools.getChildElements( "Style", CommonNamespaces.CNTXTNS, element );
1336            Style[] styles = new Style[el.getLength()];
1337            for ( int i = 0; i < styles.length; i++ ) {
1338                styles[i] = createStyle( el.item( i ), layerName, server );
1339            }
1340            StyleList styleList = null;
1341            try {
1342                styleList = new StyleList( styles );
1343            } catch ( Exception e ) {
1344                LOG.logDebug( e.getMessage(), e );
1345                throw new XMLParsingException( "could not create context stylelist", e );
1346            }
1347    
1348            return styleList;
1349        }
1350    
1351        /**
1352         * creates an instance of a class encapsulating a description of a Style
1353         * 
1354         * @param element
1355         *            <Style>
1356         * 
1357         * @return instance of <tt>Style</tt>
1358         * 
1359         * @throws XMLParsingException
1360         */
1361        private static Style createStyle( Element element, String layerName, Server server )
1362                                throws XMLParsingException {
1363    
1364            Style style = null;
1365    
1366            String tmp = XMLTools.getAttrValue( element, null, "current", null );
1367            boolean current = "1".equals( tmp ) || "true".equals( tmp );
1368    
1369            Element elem = XMLTools.getChildElement( "SLD", CommonNamespaces.CNTXTNS, element );
1370            if ( elem != null ) {
1371                SLD sld = createSLD( elem );
1372                try {
1373                    style = new Style( sld, current );
1374                } catch ( Exception e ) {
1375                    throw new XMLParsingException( "could not create context style", e );
1376                }
1377            } else {
1378                String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1379                String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
1380                String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
1381                // <LegendURL>
1382                elem = XMLTools.getChildElement( "LegendURL", CommonNamespaces.CNTXTNS, element );
1383                ImageURL legendURL = null;
1384                if ( elem != null ) {
1385                    legendURL = createImageURL( elem );
1386                } else {
1387                    try {
1388                        legendURL = createLegendURL( name, layerName, server );
1389                    } catch ( Exception e ) {
1390                        throw new XMLParsingException( "could not create context style", e );
1391                    }
1392                }
1393                try {
1394                    style = new Style( name, title, abstract_, legendURL, current );
1395                } catch ( Exception e ) {
1396                    LOG.logDebug( e.getMessage(), e );
1397                    throw new XMLParsingException( "could not create context style", e );
1398                }
1399            }
1400    
1401            return style;
1402        }
1403    
1404        /**
1405         * creates a legendURL for a style/layer by evaluating the servers capabilities the layer is servered by.
1406         * 
1407         * @return the image url.
1408         * @throws XMLParsingException
1409         */
1410        private static ImageURL createLegendURL( String styleName, String layerName, Server server )
1411                                throws XMLParsingException {
1412    
1413            WMSCapabilities capa = (WMSCapabilities) server.getCapabilities();
1414            ImageURL legendURL = null;
1415            if ( capa != null ) {
1416                org.deegree.ogcwebservices.wms.capabilities.Layer layer = capa.getLayer( layerName );
1417                // null layer will produce NullPointerException@layer.getStyles()
1418                if ( layer == null ) {
1419                    LOG.logDebug( "LayerName: " + layerName + " does not exist in the WMSCapabilities" );
1420                }
1421                // if layer is null, no legend is needed!
1422                if ( layer != null ) {
1423                    org.deegree.ogcwebservices.wms.capabilities.Style[] styles = layer.getStyles();
1424                    org.deegree.ogcwebservices.wms.capabilities.Style style = null;
1425                    for ( int i = 0; i < styles.length; i++ ) {
1426                        // find responsible style definition
1427                        style = styles[i];
1428                        if ( style.getName().equals( styleName ) ) {
1429                            break;
1430                        }
1431                    }
1432    
1433                    LegendURL[] urls = null;
1434    
1435                    if ( style != null ) {
1436                        urls = style.getLegendURL();
1437                    }
1438    
1439                    if ( urls != null && urls.length > 0 && urls[0] != null ) {
1440                        // if style has defined LegendURL(s) take the first
1441                        legendURL = new ImageURL( urls[0].getWidth(), urls[0].getHeight(), urls[0].getFormat(),
1442                                                  urls[0].getOnlineResource() );
1443                    } else {
1444                        // create a GetLegendGraphic request as style URL if the server
1445                        // supports GetLegendGraphic operation
1446                        OperationsMetadata om = capa.getOperationMetadata();
1447                        Operation operation = om.getOperation( new QualifiedName( "GetLegendGraphic" ) );
1448                        if ( operation != null ) {
1449                            HTTP http = (HTTP) operation.getDCP().get( 0 );
1450                            URL url = http.getGetOnlineResources().get( 0 );
1451                            StringBuffer sb = new StringBuffer( 500 );
1452                            sb.append( OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) );
1453                            GetLegendGraphic glg = GetLegendGraphic.create( "12", capa.getVersion(), layerName, styleName,
1454                                                                            null, null, 1, null, null, "image/jpeg", 20,
1455                                                                            20, null, null );
1456                            try {
1457                                sb.append( glg.getRequestParameter() );
1458                                url = new URL( sb.toString() );
1459                                legendURL = new ImageURL( 20, 20, "image/jpeg", url );
1460                            } catch ( Exception shouldNeverHappen ) {
1461                                shouldNeverHappen.printStackTrace();
1462                            }
1463                        }
1464                    }
1465                }
1466            }
1467    
1468            return legendURL;
1469        }
1470    
1471        /**
1472         * creates an instance of a class encapsulating a description of a Style based on a SLD
1473         * 
1474         * @param element
1475         *            <SLD>
1476         * 
1477         * @return instance of <tt>SLD</tt>
1478         * 
1479         * @throws XMLParsingException
1480         */
1481        private static SLD createSLD( Element element )
1482                                throws XMLParsingException {
1483    
1484            SLD sld = null;
1485    
1486            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1487            String title = XMLTools.getStringValue( "Title", CommonNamespaces.CNTXTNS, element, null );
1488    
1489            Element elem = XMLTools.getChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
1490            try {
1491                if ( elem != null ) {
1492                    URL onlineResource = createOnlineResource( elem );
1493                    sld = new SLD( name, title, onlineResource );
1494                } else {
1495                    elem = XMLTools.getChildElement( "StyledLayerDescriptor", CommonNamespaces.SLDNS, element );
1496                    if ( elem != null ) {
1497                        XMLFragment xml = new XMLFragment();
1498                        xml.setRootElement( elem );
1499                        StyledLayerDescriptor styledLayerDescriptor = SLDFactory.createSLD( xml );
1500                        sld = new SLD( name, title, styledLayerDescriptor );
1501                    } else {
1502                        FeatureTypeStyle fts = SLDFactory.createFeatureTypeStyle( elem );
1503                        sld = new SLD( name, title, fts );
1504                    }
1505                }
1506            } catch ( Exception e ) {
1507                LOG.logDebug( e.getMessage(), e );
1508                throw new XMLParsingException( "couldn't create map context SLD", e );
1509            }
1510    
1511            return sld;
1512        }
1513    
1514        /**
1515         * creates an instance of a class encapsulating the deegree specific extensions of a Layer
1516         * 
1517         * @param element
1518         *            Extension
1519         * @param user
1520         * @param sessionID
1521         * 
1522         * @return instance of <tt>LayerExtension</tt>
1523         * 
1524         * @throws XMLParsingException
1525         */
1526        private static LayerExtension createLayerExtension( Element element, User user, String sessionID )
1527                                throws XMLParsingException {
1528    
1529            LayerExtension le = null;
1530            if ( element != null ) {
1531    
1532                String tmp = XMLTools.getNodeAsString( element, "./dgcntxt:UseAuthentication/text()",
1533                                                       CommonNamespaces.getNamespaceContext(), "NONE" );
1534                int ua = LayerExtension.NONE;
1535                if ( "sessionID".equalsIgnoreCase( tmp ) ) {
1536                    ua = LayerExtension.SESSIONID;
1537                } else if ( "user/password".equalsIgnoreCase( tmp ) ) {
1538                    ua = LayerExtension.USERPASSWORD;
1539                }
1540    
1541                DataService dataService = null;
1542                Element elem = XMLTools.getChildElement( "DataService", CommonNamespaces.DGCNTXTNS, element );
1543                if ( elem != null ) {
1544                    Element el = XMLTools.getRequiredChildElement( "Server", CommonNamespaces.CNTXTNS, elem );
1545                    Server server = createServer( el, user, sessionID, ua );
1546                    String geoType = XMLTools.getStringValue( "GeometryType", CommonNamespaces.DGCNTXTNS, elem, null );
1547                    String featureType = XMLTools.getStringValue( "FeatureType", CommonNamespaces.DGCNTXTNS, elem, null );
1548                    dataService = new DataService( server, featureType, geoType );
1549                }
1550                boolean masterLayer = false;
1551                elem = XMLTools.getChildElement( "MasterLayer", CommonNamespaces.DGCNTXTNS, element );
1552                if ( elem != null ) {
1553                    String s = XMLTools.getStringValue( elem );
1554                    masterLayer = "true".equals( s ) || "1".equals( s );
1555                }
1556    
1557                boolean selectedForFI = false;
1558                elem = XMLTools.getChildElement( "SelectedForQuery", CommonNamespaces.DGCNTXTNS, element );
1559                if ( elem != null ) {
1560                    String s = XMLTools.getStringValue( elem );
1561                    selectedForFI = "true".equals( s ) || "1".equals( s );
1562                }
1563    
1564                int parentNodeId = 1;
1565                elem = XMLTools.getChildElement( "parentNodeId", CommonNamespaces.DGCNTXTNS, element );
1566                if ( elem != null ) {
1567                    parentNodeId = Integer.parseInt( XMLTools.getStringValue( elem ) );
1568                }
1569                boolean showLegendGraphic = false;
1570                elem = XMLTools.getChildElement( "showLegendGraphic", CommonNamespaces.DGCNTXTNS, element );
1571                if ( elem != null ) {
1572                    String s = XMLTools.getStringValue( elem );
1573                    showLegendGraphic = "true".equals( s ) || "1".equals( s );
1574                }
1575    
1576                String identifier = null;
1577                elem = XMLTools.getChildElement( "identifier", CommonNamespaces.DGCNTXTNS, element );
1578                if ( elem != null ) {
1579                    identifier = XMLTools.getStringValue( elem );
1580                }
1581    
1582                le = new LayerExtension( dataService, masterLayer, 0, Double.MAX_VALUE, selectedForFI, ua, parentNodeId,
1583                                         showLegendGraphic, identifier );
1584    
1585            } else {
1586                le = new LayerExtension();
1587            }
1588    
1589            return le;
1590        }
1591    
1592        /**
1593         * Use information form extension and server elements of a layer to set a scaleHint.
1594         * 
1595         * If layer extension contains scale hints (min, max), then these values are taken. Otherwise, the information is
1596         * taken from the WMS capabilities by using {@link #getScaleHintFromCapabilities(Server, String, User, String, int)}
1597         * 
1598         * @param extElem
1599         * @param name
1600         * @param extension
1601         * @param server
1602         * @param user
1603         * @param sessionID
1604         * @param useAuthentication
1605         * @throws XMLParsingException
1606         */
1607        private static void setScaleHint( Element extElem, String name, LayerExtension extension, Server server, User user,
1608                                          String sessionID, int useAuthentication )
1609                                throws XMLParsingException {
1610    
1611            // <deegree:ScaleHint min="0.0" max="41.0"/>
1612            Element elem = null;
1613            if ( extElem != null ) {
1614                elem = XMLTools.getChildElement( "ScaleHint", CommonNamespaces.DGCNTXTNS, extElem );
1615            }
1616    
1617            double min = 0;
1618            double max = Double.MAX_VALUE;
1619            if ( elem != null ) {
1620                // read scale hint from WebMapContext document
1621                String s = XMLTools.getRequiredAttrValue( "min", null, elem );
1622                min = Double.parseDouble( s );
1623                s = XMLTools.getRequiredAttrValue( "max", null, elem );
1624                max = Double.parseDouble( s );
1625            } else {
1626                // reade scaleHint from WMS Capabilities
1627                double[] sc = getScaleHintFromCapabilities( server, name, user, sessionID, useAuthentication );
1628                min = sc[0];
1629                max = sc[1];
1630            }
1631            extension.setMinScaleHint( min );
1632            extension.setMaxScaleHint( max );
1633        }
1634    
1635        /**
1636         * taken from d1 and adjusted for d2.
1637         * 
1638         * TODO: check if inconsistencies arise regarding user-dependant scaleHint, because of using {@link #wmsCache}.
1639         * 
1640         * @param server
1641         * @param layerName
1642         * @param user
1643         * @param sessionID
1644         * @param useAuthentication
1645         * @return
1646         */
1647        private static double[] getScaleHintFromCapabilities( Server server, String layerName, User user, String sessionID,
1648                                                              int useAuthentication ) {
1649    
1650            double[] sc = new double[] { 0, Double.MAX_VALUE };
1651            WMSCapabilities capa = null;
1652    
1653            // capabilities have not been stored in cache before. getting the capabilities for the specified user
1654            if ( wmsCache.get( server.getOnlineResource() ) == null ) {
1655                capa = (WMSCapabilities) getCapabilities( server.getOnlineResource(), server.getService(),
1656                                                          server.getVersion(), user, sessionID, useAuthentication );
1657            } else {
1658                // get capabilities from cache.
1659                // May cause an inconsistency problem, if cache contains capabilities of a different but the specified user.
1660                // Could be handled with different caches for different users, but this would cause performance problems.
1661                capa = (WMSCapabilities) wmsCache.get( server.getOnlineResource() );
1662            }
1663            if ( capa != null ) {
1664                wmsCache.put( server.getOnlineResource(), capa );
1665                org.deegree.ogcwebservices.wms.capabilities.Layer lay = capa.getLayer( layerName );
1666                if ( lay != null ) {
1667                    try {
1668                        sc[0] = lay.getScaleHint().getMin();
1669                        sc[1] = lay.getScaleHint().getMax();
1670                    } catch ( Exception e ) {
1671                    }
1672                }
1673            }
1674            return sc;
1675        }
1676    
1677        /**
1678         * returns the capabilities for the passed server. The capabilities are read directly from the server or from the
1679         * loacal cache.
1680         * 
1681         * @param url
1682         * @param service
1683         * @param version
1684         * @param user
1685         * @param sessionID
1686         * @param useAuthentication
1687         * @return he capabilities for the passed server. The capabilities are read directly from the server or from the
1688         *         loacal cache.
1689         */
1690        private static OGCCapabilities getCapabilities( URL url, String service, String version, User user,
1691                                                        String sessionID, int useAuthentication ) {
1692    
1693            OGCCapabilities capa = null;
1694    
1695            String href = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() );
1696            if ( href.toLowerCase().startsWith( "http://" ) || href.toLowerCase().startsWith( "https://" ) ) {
1697                if ( "OGC:WMS".equals( service ) ) {
1698                    // is a HTTP URL so GetCapabilities request must be constructed
1699                    if ( "1.0.0".equals( version ) ) {
1700                        href = StringTools.concat( 1000, href, "request=capabilities&service=WMS", "&WMTVER=", version );
1701                    } else {
1702                        href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WMS", "&version=", version );
1703                    }
1704    
1705                } else if ( "OGC:WFS".equals( service ) ) {
1706                    // is a HTTP URL so GetCapabilities request must be constructed
1707                    href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WFS", "&version=", version );
1708    
1709                } else if ( "OGC:WCS".equals( service ) ) {
1710                    // is a HTTP URL so GetCapabilities request must be constructed
1711                    href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WCS", "&version=", version );
1712    
1713                }
1714    
1715                if ( useAuthentication == LayerExtension.SESSIONID ) {
1716                    href = StringTools.concat( 1000, href, "&sessionID=", sessionID );
1717                } else if ( useAuthentication == LayerExtension.USERPASSWORD ) {
1718                    href = StringTools.concat( 1000, href, "&user=", user.getName(), "&password=", user.getPassword() );
1719                }
1720            }
1721    
1722            if ( wmsCache.get( url ) == null && "OGC:WMS".equals( service ) ) {
1723                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1724                capa = parseCapabilities( href, service );
1725                if ( capa != null ) {
1726                    // write capabilities into local cache
1727                    wmsCache.put( url, (WMSCapabilities) capa );
1728                }
1729            } else if ( "OGC:WMS".equals( service ) ) {
1730                LOG.logDebug( "get WMS capabilities from cache" );
1731                capa = wmsCache.get( url );
1732            } else if ( wfsCache.get( url ) == null && "OGC:WFS".equals( service ) ) {
1733                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1734                capa = parseCapabilities( href, service );
1735                if ( capa != null ) {
1736                    // write capabilities into local cache
1737                    wfsCache.put( url, (WFSCapabilities) capa );
1738                }
1739            } else if ( "OGC:WFS".equals( service ) ) {
1740                LOG.logDebug( "get WFS capabilities from cache" );
1741                capa = wfsCache.get( url );
1742            } else if ( wcsCache.get( url ) == null && "OGC:WCS".equals( service ) ) {
1743                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1744                capa = parseCapabilities( href, service );
1745                if ( capa != null ) {
1746                    // write capabilities into local cache
1747                    wcsCache.put( url, (WCSCapabilities) capa );
1748                }
1749            } else if ( "OGC:WFS".equals( service ) ) {
1750                LOG.logDebug( "get WCS capabilities from cache" );
1751                capa = wcsCache.get( url );
1752            }
1753    
1754            return capa;
1755        }
1756    
1757        /**
1758         * 
1759         * @param href
1760         * @param service
1761         * @return the capabilities bean.
1762         */
1763        private static OGCCapabilities parseCapabilities( String href, String service ) {
1764    
1765            OGCCapabilities capa = null;
1766            try {
1767                URL url = null;
1768                Reader reader = null;
1769    
1770                // consider that the reference to the capabilities may has been
1771                // made by a file URL to a local copy
1772                if ( href.toLowerCase().startsWith( "http://" ) || href.toLowerCase().startsWith( "https://" ) ) {
1773                    HttpClient httpclient = new HttpClient();
1774                    httpclient = WebUtils.enableProxyUsage( httpclient, new URL( href ) );
1775                    int timeout = Integer.parseInt( Messages.getString( "WebMapContextFactory.timeout" ) );
1776                    httpclient.getHttpConnectionManager().getParams().setSoTimeout( timeout );
1777    
1778                    GetMethod httpget = new GetMethod( href );
1779                    LOG.logDebug( "GetCapabilities: ", href );
1780    
1781                    httpclient.executeMethod( httpget );
1782                    reader = new InputStreamReader( httpget.getResponseBodyAsStream() );
1783                } else {
1784                    if ( href.endsWith( "?" ) ) {
1785                        url = new URL( href.substring( 0, href.length() - 1 ) );
1786                    }
1787                    reader = new InputStreamReader( url.openStream() );
1788                }
1789    
1790                OGCCapabilitiesDocument doc = null;
1791                if ( "OGC:WMS".equals( service ) ) {
1792                    doc = new WMSCapabilitiesDocument();
1793                    doc.load( reader, XMLFragment.DEFAULT_URL );
1794                    doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() );
1795                } else if ( "OGC:WFS".equals( service ) ) {
1796                    doc = new WFSCapabilitiesDocument();
1797                    doc.load( reader, XMLFragment.DEFAULT_URL );
1798                } else if ( "OGC:WCS".equals( service ) ) {
1799                    doc = new WCSCapabilitiesDocument();
1800                    doc.load( reader, XMLFragment.DEFAULT_URL );
1801                } else {
1802                    throw new XMLParsingException( "not supported service type: " + service );
1803                }
1804    
1805                capa = doc.parseCapabilities();
1806            } catch ( Exception e ) {
1807                LOG.logWarning( "could not read capabilities: " + href );
1808                // LOG.logError( e.getMessage(), e );
1809                return null;
1810            }
1811            return capa;
1812        }
1813    
1814        // /**
1815        // * @param mapServer
1816        // * @param layer
1817        // * @return ScaleHint
1818        // */
1819        // private static double[] getScaleHintFromCapabilities( Server mapServer, String layer ) {
1820        //
1821        // double[] sc = new double[] { 0, 9999999 };
1822        // WMSCapabilities capa = (WMSCapabilities) mapServer.getCapabilities();
1823        // if ( capa != null ) {
1824        // org.deegree.ogcwebservices.wms.capabilities.Layer lay = capa.getLayer( layer );
1825        // if ( lay != null ) {
1826        // sc[0] = lay.getScaleHint().getMin();
1827        // sc[1] = lay.getScaleHint().getMax();
1828        // }
1829        // }
1830        // return sc;
1831        // }
1832    
1833        /**
1834         * creates a list (String[]) containing the name of the JavaScript files used by the moudle
1835         * 
1836         * @param element
1837         *            <Module>
1838         * 
1839         * @return instance of <tt>String[]</tt>
1840         * 
1841         */
1842        private static String[] createModuleJSList( Element element ) {
1843            String[] moduleJS = null;
1844            if ( element != null ) {
1845                ElementList el = XMLTools.getChildElements( "ModuleJS", CommonNamespaces.DGCNTXTNS, element );
1846                moduleJS = new String[el.getLength()];
1847                for ( int i = 0; i < el.getLength(); i++ ) {
1848                    moduleJS[i] = ( (Text) el.item( i ).getFirstChild() ).getData();
1849                }
1850            }
1851    
1852            return moduleJS;
1853        }
1854    }