001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/csw/CatalogueService.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2004 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/exse/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Meckenheimer Allee 176
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    
044    package org.deegree.ogcwebservices.csw;
045    
046    import java.net.URL;
047    import java.util.HashMap;
048    import java.util.Map;
049    
050    import org.deegree.framework.log.ILogger;
051    import org.deegree.framework.log.LoggerFactory;
052    import org.deegree.framework.trigger.TriggerProvider;
053    import org.deegree.ogcwebservices.InvalidParameterValueException;
054    import org.deegree.ogcwebservices.MissingParameterValueException;
055    import org.deegree.ogcwebservices.OGCWebService;
056    import org.deegree.ogcwebservices.OGCWebServiceException;
057    import org.deegree.ogcwebservices.OGCWebServiceRequest;
058    import org.deegree.ogcwebservices.csw.capabilities.CatalogueGetCapabilities;
059    import org.deegree.ogcwebservices.csw.capabilities.CatalogueOperationsMetadata;
060    import org.deegree.ogcwebservices.csw.configuration.CatalogueConfiguration;
061    import org.deegree.ogcwebservices.csw.configuration.CatalogueConfigurationDocument;
062    import org.deegree.ogcwebservices.csw.discovery.DescribeRecord;
063    import org.deegree.ogcwebservices.csw.discovery.Discovery;
064    import org.deegree.ogcwebservices.csw.discovery.GetDomain;
065    import org.deegree.ogcwebservices.csw.discovery.GetRecordById;
066    import org.deegree.ogcwebservices.csw.discovery.GetRecords;
067    import org.deegree.ogcwebservices.csw.manager.Harvest;
068    import org.deegree.ogcwebservices.csw.manager.Manager;
069    import org.deegree.ogcwebservices.csw.manager.Transaction;
070    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
071    import org.deegree.ogcwebservices.wfs.RemoteWFService;
072    import org.deegree.ogcwebservices.wfs.WFService;
073    import org.deegree.ogcwebservices.wfs.WFServiceFactory;
074    import org.deegree.ogcwebservices.wfs.XMLFactory;
075    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
076    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
077    import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration;
078    import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument;
079    
080    /**
081     * The Catalogue Service class provides the foundation for an OGC catalogue service. The Catalogue Service class
082     * directly includes only the serviceTypeID attribute. In most cases, this attribute will not be directly visible to
083     * catalogue clients.
084     * <p>
085     * The catalog service is an implementation of the OpenGIS Catalogue Service Specification 2.0.
086     * </p>
087     * 
088     * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a>
089     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
090     * 
091     * @author last edited by: $Author: rbezema $
092     * 
093     * @version $Revision: 7253 $, $Date: 2007-05-22 11:35:33 +0200 (Di, 22 Mai 2007) $
094     * @see <a href="http://www.opengis.org/specs/">OGC Specification </a>
095     */
096    
097    public class CatalogueService implements OGCWebService {
098    
099        private static final ILogger LOG = LoggerFactory.getLogger( CatalogueService.class );
100    
101        private static final TriggerProvider TP = TriggerProvider.create( CatalogueService.class );
102    
103        private Discovery discovery;
104    
105        private Manager manager;
106    
107        private CatalogueConfiguration serviceConfiguration;
108    
109        static Map<URL, OGCWebService> wfsMap = new HashMap<URL, OGCWebService>();
110    
111        /**
112         * Creates a new <code>CatalogService</code> instance.
113         * 
114         * @param config
115         * 
116         * @return new <code>CatalogService</code> instance.
117         * @throws OGCWebServiceException
118         */
119        public static final CatalogueService create( CatalogueConfiguration config ) throws OGCWebServiceException {
120            // get WFS: local or remote
121            OGCWebService wfsResource = null;
122            try {
123                CatalogueConfigurationDocument document = new CatalogueConfigurationDocument();
124                document.setSystemId( config.getSystemId() );
125    
126                URL wfsCapabilitiesFileURL = document.resolve( config.getDeegreeParams()
127                                                                     .getWfsResource()
128                                                                     .getHref()
129                                                                     .toString() );
130                if ( wfsMap.get( wfsCapabilitiesFileURL ) == null ) {
131                    if ( wfsCapabilitiesFileURL.getProtocol().equals( "http" ) ) {
132                        WFSCapabilitiesDocument capaDoc = new WFSCapabilitiesDocument();
133                        capaDoc.load( wfsCapabilitiesFileURL );
134                        WFSCapabilities capabilities = (WFSCapabilities) capaDoc.parseCapabilities();
135                        LOG.logInfo( "Creating remote WFS with capabilities file " + wfsCapabilitiesFileURL );
136                        wfsResource = new RemoteWFService( capabilities );
137                    } else {
138                        WFSConfigurationDocument capaDoc = new WFSConfigurationDocument();
139                        capaDoc.load( wfsCapabilitiesFileURL );
140                        WFSConfiguration conf = capaDoc.getConfiguration();
141                        LOG.logInfo( "CS-W service: Creating local WFS with capabilities file " + wfsCapabilitiesFileURL );
142                        wfsResource = WFServiceFactory.createInstance( conf );
143                        LOG.logDebug( "CS-W service: The localwfs was has been successfully created, it's capabilties are: " +  
144                                      XMLFactory.export( (WFSCapabilities)wfsResource.getCapabilities() ).getAsPrettyString());
145                    }
146                    wfsMap.put( wfsCapabilitiesFileURL, wfsResource );
147                } else {
148                    wfsResource = wfsMap.get( wfsCapabilitiesFileURL );
149                }
150            } catch ( Exception e ) {
151                LOG.logError( "Error creating WFS for CSW", e );
152                throw new OGCWebServiceException( CatalogueService.class.getName(),
153                                                  "Error creating WFS for CSW: " + e.getMessage() );
154            }
155    
156            // initialize manager and discovery
157            return new CatalogueService( config, (WFService) wfsResource );
158        }
159    
160        /**
161         * 
162         * @param config
163         * @param wfsService
164         * @throws OGCWebServiceException
165         */
166        private CatalogueService( CatalogueConfiguration config, WFService wfsService ) throws OGCWebServiceException {
167            this.serviceConfiguration = config;
168            this.discovery = new Discovery( wfsService, config );
169            CatalogueOperationsMetadata com = (CatalogueOperationsMetadata) config.getOperationsMetadata();
170            if ( com.getHarvest() != null || com.getTransaction() != null ) {
171                try {
172                    this.manager = new Manager( wfsService, config );
173                } catch ( MissingParameterValueException e ) {
174                    LOG.logError( e.getMessage(), e );
175                    throw new OGCWebServiceException( getClass().getName(), e.getMessage() );
176                }
177            }
178        }
179    
180        /**
181         * Returns the OGC-capabilities of the service.
182         * 
183         * @return the OGC-capabilities of the service.
184         * @todo analyze incoming request! return only requested sections
185         */
186        public OGCCapabilities getCapabilities() {
187            return this.serviceConfiguration;
188        }
189    
190        /**
191         * Returns the service type (CSW).
192         * 
193         * @return the service type (CSW).
194         */
195        public String getServiceTypeId() {
196            return this.serviceConfiguration.getServiceIdentification().getServiceType().getCode();
197        }
198    
199        /**
200         * @return Version
201         */
202        public String getVersion() {
203            return this.serviceConfiguration.getVersion();
204        }
205    
206        /**
207         * Method for event based request processing.
208         * 
209         * @param request
210         *            request object containing the request
211         * @return an Object which may be one of the following <ul>
212         * <li>DescribeRecordResult</li>
213         * <li>GetRecordResult</li>
214         * <li>GetRecordByIdResult</li>
215         * <li>TransactionResult</li>
216         * <li>EchoRequest</li>
217         * <li>OGCCapabilities</li>
218         * @throws OGCWebServiceException
219         * 
220         * @todo validation of requested version against accepted versions
221         * @todo return type
222         */
223        public Object doService( OGCWebServiceRequest request ) throws OGCWebServiceException {
224    
225            request = (OGCWebServiceRequest) TP.doPreTrigger( this, request )[0];
226    
227            Object response = null;
228    
229            if ( request instanceof DescribeRecord ) {
230                response = this.getDiscovery().describeRecordType( (DescribeRecord) request );
231            } else if ( request instanceof GetDomain ) {
232                throw new OGCWebServiceException( getClass().getName(), "Operation GetDomain is not implement yet" );
233                // TODO is not implemented
234                // response = this.getDiscovery().getDomain( (GetDomain) request );
235            } else if ( request instanceof GetRecords ) {
236                response = this.getDiscovery().query( (GetRecords) request );
237            } else if ( request instanceof GetRecordById ) {
238                response = this.getDiscovery().query( (GetRecordById) request );
239            } else if ( request instanceof Transaction ) {
240                response = this.getManager().transaction( (Transaction) request );
241            } else if ( request instanceof Harvest ) {
242                response = this.getManager().harvestRecords( (Harvest) request );
243            } else if ( request instanceof CatalogueGetCapabilities ) {
244                LOG.logDebug( "GetCapabilities for version:" + request.getVersion(), request );
245                String[] acceptVersions = ( (CatalogueGetCapabilities) request ).getAcceptVersions();
246                boolean versionOk = false;
247                if ( acceptVersions == null || acceptVersions.length == 0 ) {
248                    versionOk = true;
249                } else {
250                    for ( int i = 0; i < acceptVersions.length; i++ ) {
251                        if ( acceptVersions[i].equals( "2.0.0" ) ) {
252                            versionOk = true;
253                            break;
254                        }
255                    }
256                }
257                if ( versionOk ) {
258                    response = this.getCapabilities();
259                } else {
260                    throw new InvalidParameterValueException( "Unsupported version requested, only version 2.0.0 is supported." );
261                }
262            } else {
263                throw new OGCWebServiceException( "Invalid request type: '" + request.getClass().getName() + "'." );
264            }
265    
266            return TP.doPostTrigger( this, response )[0];
267        }
268    
269        /**
270         * @return Returns the discovery.
271         * 
272         */
273        public Discovery getDiscovery() {
274            return discovery;
275        }
276    
277        /**
278         * @return the manager.
279         * @throws OGCWebServiceException
280         */
281        public Manager getManager() throws OGCWebServiceException {
282            if ( manager == null ) {
283                throw new OGCWebServiceException( getClass().getName(),
284                                                  "CSW Manager class for " + "handling transactional requests is not initialized. Please verfiy, "
285                                                                          + "that you have defined Transaction and/or Harvest in the "
286                                                                          + "OperationMetadata section of your capabilities/configuration." );
287            }
288            return manager;
289        }
290    
291    }